## @file
# Manager tree structure and tests
## @class
# Manager tree structure and tests
package Lemonldap::NG::Manager::_Struct;
use strict;
use Lemonldap::NG::Common::Conf::SAML::Metadata;
use Lemonldap::NG::Common::Regexp;
our $VERSION = '1.3.0';
## @method protected hashref cstruct(hashref h,string k)
# Merge $h with the structure produced with $k and return it.
# Used to manage virtual hosts, and metadatas (IDP, SP).
#@param $h Result of struct()
#@param $k Full path of the key
#@return Tree structure
sub cstruct {
shift;
my ( $h, $k ) = @_;
my @tmp = split( /\//, $k );
return $h unless ( scalar(@tmp) > 1 );
my $k1 = $tmp[0];
my $k2 = $tmp[1];
if ( $k1 =~ /^virtualHosts/i ) {
%$h = (
%$h,
virtualHosts => {
$k2 => {
_nodes => [
qw(rules:rules:rules headers post:post:post vhostOptions)
],
rules => {
_nodes => ["hash:/locationRules/$k2:rules:rules"],
_js => 'rulesRoot',
_help => 'rules',
},
headers => {
_nodes => ["hash:/exportedHeaders/$k2"],
_js => 'hashRoot',
_help => 'headers',
},
post => {
_nodes => ["post:/post/$k2:post:post"],
_js => 'postRoot',
_help => 'post',
},
vhostOptions => {
_nodes => [
qw(vhostPort vhostHttps vhostMaintenance vhostAliases)
],
vhostPort => "int:/vhostOptions/$k2/vhostPort",
vhostHttps => "trool:/vhostOptions/$k2/vhostHttps",
vhostMaintenance =>
"bool:/vhostOptions/$k2/vhostMaintenance",
vhostAliases => "text:/vhostOptions/$k2/vhostAliases",
_help => 'vhostOptions',
},
}
}
);
}
elsif ( $k1 =~ /^samlIDPMetaDataNode/i ) {
%$h = (
%$h,
samlIDPMetaDataNode => {
$k2 => {
_nodes => [
qw(samlIDPMetaDataXML samlIDPMetaDataExportedAttributes samlIDPMetaDataOptions)
],
samlIDPMetaDataExportedAttributes => {
_nodes => [
"hash:/samlIDPMetaDataExportedAttributes/$k2"
. ":samlIDPMetaDataExportedAttributes:samlAttribute"
],
_js => 'samlAttributeRoot',
_help => 'samlIDPExportedAttributes',
},
samlIDPMetaDataXML => "samlmetadata:/samlIDPMetaDataXML/$k2"
. ":samlIDPMetaDataXML:filearea",
samlIDPMetaDataOptions => {
_nodes => [
qw(samlIDPMetaDataOptionsResolutionRule samlIDPMetaDataOptionsAuthnRequest samlIDPMetaDataOptionsSession samlIDPMetaDataOptionsSignature samlIDPMetaDataOptionsBinding samlIDPMetaDataOptionsSecurity)
],
_help => 'samlIDPOptions',
samlIDPMetaDataOptionsResolutionRule =>
"textarea:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsResolutionRule",
samlIDPMetaDataOptionsAuthnRequest => {
_nodes => [
qw(samlIDPMetaDataOptionsNameIDFormat samlIDPMetaDataOptionsForceAuthn samlIDPMetaDataOptionsIsPassive samlIDPMetaDataOptionsAllowProxiedAuthn samlIDPMetaDataOptionsAllowLoginFromIDP samlIDPMetaDataOptionsRequestedAuthnContext)
],
samlIDPMetaDataOptionsNameIDFormat =>
"text:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsNameIDFormat"
. ":samlIDPOptions:nameIdFormatParams",
samlIDPMetaDataOptionsForceAuthn =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsForceAuthn",
samlIDPMetaDataOptionsIsPassive =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsIsPassive",
samlIDPMetaDataOptionsAllowProxiedAuthn =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsAllowProxiedAuthn",
samlIDPMetaDataOptionsAllowLoginFromIDP =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsAllowLoginFromIDP",
samlIDPMetaDataOptionsRequestedAuthnContext =>
"text:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsRequestedAuthnContext"
. ":samlIDPOptions:authnContextParams",
},
samlIDPMetaDataOptionsSession => {
_nodes => [
qw(samlIDPMetaDataOptionsAdaptSessionUtime samlIDPMetaDataOptionsForceUTF8)
],
samlIDPMetaDataOptionsAdaptSessionUtime =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsAdaptSessionUtime",
samlIDPMetaDataOptionsForceUTF8 =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsForceUTF8",
},
samlIDPMetaDataOptionsSignature => {
_nodes => [
qw(samlIDPMetaDataOptionsSignSSOMessage samlIDPMetaDataOptionsCheckSSOMessageSignature samlIDPMetaDataOptionsSignSLOMessage samlIDPMetaDataOptionsCheckSLOMessageSignature)
],
samlIDPMetaDataOptionsSignSSOMessage =>
"trool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsSignSSOMessage",
samlIDPMetaDataOptionsCheckSSOMessageSignature =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsCheckSSOMessageSignature",
samlIDPMetaDataOptionsSignSLOMessage =>
"trool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsSignSLOMessage",
samlIDPMetaDataOptionsCheckSLOMessageSignature =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsCheckSLOMessageSignature",
},
samlIDPMetaDataOptionsBinding => {
_nodes => [
qw(samlIDPMetaDataOptionsSSOBinding samlIDPMetaDataOptionsSLOBinding)
],
samlIDPMetaDataOptionsSSOBinding =>
"text:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsSSOBinding"
. ":samlIDPOptions:bindingParams",
samlIDPMetaDataOptionsSLOBinding =>
"text:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsSLOBinding"
. ":samlIDPOptions:bindingParams",
},
samlIDPMetaDataOptionsSecurity => {
_nodes => [
qw(samlIDPMetaDataOptionsEncryptionMode samlIDPMetaDataOptionsCheckConditions)
],
samlIDPMetaDataOptionsEncryptionMode =>
"text:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsEncryptionMode:samlIDPOptions:encryptionModeParams",
samlIDPMetaDataOptionsCheckConditions =>
"bool:/samlIDPMetaDataOptions/$k2/samlIDPMetaDataOptionsCheckConditions",
},
},
}
}
);
}
elsif ( $k1 =~ /^samlSPMetaDataNode/i ) {
%$h = (
%$h,
samlSPMetaDataNode => {
$k2 => {
_nodes => [
qw(samlSPMetaDataXML samlSPMetaDataExportedAttributes samlSPMetaDataOptions)
],
samlSPMetaDataExportedAttributes => {
_nodes => [
"hash:/samlSPMetaDataExportedAttributes/$k2"
. ":samlSPMetaDataExportedAttributes:samlAttribute"
],
_js => 'samlAttributeRoot',
_help => 'samlSPExportedAttributes',
},
samlSPMetaDataXML => "samlmetadata:/samlSPMetaDataXML/$k2"
. ":samlSPMetaDataXML:filearea",
samlSPMetaDataOptions => {
_nodes => [
qw(samlSPMetaDataOptionsAuthnResponse samlSPMetaDataOptionsSignature samlSPMetaDataOptionsSecurity)
],
_help => 'samlSPOptions',
samlSPMetaDataOptionsAuthnResponse => {
_nodes => [
qw(samlSPMetaDataOptionsNameIDFormat samlSPMetaDataOptionsOneTimeUse)
],
samlSPMetaDataOptionsNameIDFormat =>
"text:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsNameIDFormat"
. ":samlSPOptions:nameIdFormatParams",
samlSPMetaDataOptionsOneTimeUse =>
"bool:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsOneTimeUse",
},
samlSPMetaDataOptionsSignature => {
_nodes => [
qw(samlSPMetaDataOptionsSignSSOMessage samlSPMetaDataOptionsCheckSSOMessageSignature samlSPMetaDataOptionsSignSLOMessage samlSPMetaDataOptionsCheckSLOMessageSignature)
],
samlSPMetaDataOptionsSignSSOMessage =>
"trool:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsSignSSOMessage",
samlSPMetaDataOptionsCheckSSOMessageSignature =>
"bool:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsCheckSSOMessageSignature",
samlSPMetaDataOptionsSignSLOMessage =>
"trool:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsSignSLOMessage",
samlSPMetaDataOptionsCheckSLOMessageSignature =>
"bool:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsCheckSLOMessageSignature",
},
samlSPMetaDataOptionsSecurity => {
_nodes => [qw(samlSPMetaDataOptionsEncryptionMode)],
samlSPMetaDataOptionsEncryptionMode =>
"text:/samlSPMetaDataOptions/$k2/samlSPMetaDataOptionsEncryptionMode:samlSPOptions:encryptionModeParams",
},
},
}
}
);
}
return $h;
}
## @method protected hashref struct(hashref h,string k)
# Returns the tree structure
#@return Tree structure
sub struct {
my $self = shift;
return {
_nodes => [
qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode n:samlSPMetaDataNode)
],
_help => 'default',
######################
# GENERAL PARAMETERS #
######################
generalParameters => {
_nodes => [
qw(n:portalParams n:authParams n:issuerParams n:logParams n:cookieParams n:sessionParams cn:reloadUrls n:advancedParams)
],
_help => 'default',
# PORTAL PARAMETERS
portalParams => {
_nodes => [
qw(portal n:portalMenu n:portalCustomization n:portalCaptcha)
],
_help => 'portalParams',
portal => 'text:/portal:portal:text',
portalMenu => {
_nodes => [qw(portalModules applicationList)],
_help => 'menu',
portalModules => {
_nodes => [
qw(portalDisplayLogout portalDisplayChangePassword portalDisplayAppslist portalDisplayLoginHistory)
],
portalDisplayLogout =>
'text:/portalDisplayLogout:menu:boolOrPerlExpr',
portalDisplayChangePassword =>
'text:/portalDisplayChangePassword:menu:boolOrPerlExpr',
portalDisplayAppslist =>
'text:/portalDisplayAppslist:menu:boolOrPerlExpr',
portalDisplayLoginHistory =>
'text:/portalDisplayLoginHistory:menu:boolOrPerlExpr',
},
applicationList => {
_nodes => [
'applicationlist:/applicationList:menuCatAndApp:applicationListCategory'
],
_js => 'applicationListCategoryRoot',
_help => 'menuCatAndApp',
},
},
portalCustomization => {
_nodes => [
qw(portalSkin cn:portalSkinRules portalAutocomplete portalCheckLogins portalUserAttr portalOpenLinkInNewWindow portalAntiFrame passwordManagement)
],
_help => 'portalcustom',
portalSkin => 'text:/portalSkin:portalcustom:skinSelect',
portalSkinRules => {
_nodes => ['hash:/portalSkinRules:portalcustom:btext'],
_js => 'hashRoot',
_help => 'portalcustom',
},
portalAutocomplete => 'bool:/portalAutocomplete',
portalCheckLogins => 'bool:/portalCheckLogins',
portalUserAttr => 'text:/portalUserAttr',
portalOpenLinkInNewWindow =>
'bool:/portalOpenLinkInNewWindow',
portalAntiFrame => 'bool:/portalAntiFrame',
passwordManagement => {
_nodes => [
qw(portalDisplayResetPassword portalRequireOldPassword hideOldPassword mailOnPasswordChange)
],
portalDisplayResetPassword =>
'bool:/portalDisplayResetPassword',
portalRequireOldPassword =>
'bool:/portalRequireOldPassword',
hideOldPassword => 'bool:/hideOldPassword',
mailOnPasswordChange => 'bool:/mailOnPasswordChange',
},
},
portalCaptcha => {
_nodes => [
qw(captcha_login_enabled captcha_mail_enabled captcha_size captcha_data captcha_output)
],
captcha_login_enabled => 'bool:/captcha_login_enabled',
captcha_mail_enabled => 'bool:/captcha_mail_enabled',
captcha_size => 'int:/captcha_size',
captcha_data => 'text:/captcha_data',
captcha_output => 'text:/captcha_output',
},
},
# AUTHENTICATION / USERDB / PASSWORDDB PARAMETERS
authParams => {
# Displayed nodes depend on authentication/userDB modules choosed
_nodes => sub {
my $self = shift;
my $auth = $self->conf->{authentication}
|| $self->defaultConf()->{authentication};
my $udb = $self->conf->{userDB}
|| $self->defaultConf()->{userDB};
my $pdb = $self->conf->{passwordDB}
|| $self->defaultConf()->{passwordDB};
$auth = lc($auth);
$auth =~ s/\s.*$//; # For Multi
$udb = lc($udb);
$pdb = lc($pdb);
my %res;
foreach my $mod (
(
$auth,
( $udb ne ( $auth or $pdb ) ? $udb : () ),
( $pdb ne ( $auth or $udb ) ? $pdb : () ),
)
)
{
my $tmp = {
ad => ['ldapParams'],
ldap => ['ldapParams'],
ssl => ['sslParams'],
cas => ['casParams'],
radius => ['radiusParams'],
remote => ['remoteParams'],
proxy => ['proxyParams'],
openid => ['openIdParams'],
google => ['googleParams'],
facebook => ['facebookParams'],
twitter => ['twitterParams'],
webid => ['webIDParams'],
dbi => ['dbiParams'],
apache => ['apacheParams'],
null => ['nullParams'],
slave => ['slaveParams'],
choice => [
qw(ldapParams sslParams casParams radiusParams remoteParams proxyParams openIdParams googleParams facebookParams twitterParams webIDParams dbiParams apacheParams nullParams choiceParams slaveParams yubikeyParams browserIdParams)
],
multi => [
qw(ldapParams sslParams casParams radiusParams remoteParams proxyParams openIdParams googleParams facebookParams twitterParams webIDParams dbiParams apacheParams nullParams choiceParams slaveParams yubikeyParams browserIdParams)
],
yubikey => ['yubikeyParams'],
browserid => ['browserIdParams'],
}->{$mod};
if ($tmp) {
$res{$_}++ foreach (@$tmp);
}
}
my @u = keys %res;
# Add authentication, userDB, passwordDB and issuerDB nodes at the beginning
unshift( @u, "passwordDB" );
unshift( @u, "userDB" );
unshift( @u, "authentication" );
# Return nodes
return \@u;
},
_help => 'authParams',
authentication => 'text:/authentication:authParams:authParams',
userDB => 'text:/userDB:authParams:userdbParams',
passwordDB => 'text:/passwordDB:authParams:passworddbParams',
# LDAP
ldapParams => {
_nodes => [
qw(ldapAuthnLevel n:ldapConnection n:ldapFilters n:ldapGroups n:ldapPassword)
],
_help => 'authLDAP',
ldapAuthnLevel => 'int:/ldapAuthnLevel:authLDAPLevel:int',
ldapConnection => {
_nodes => [
qw(ldapServer ldapPort ldapBase managerDn managerPassword ldapTimeout ldapVersion ldapRaw)
],
ldapServer => 'text:/ldapServer',
ldapPort => 'int:/ldapPort',
ldapBase => 'text:/ldapBase',
managerDn => 'text:/managerDn',
managerPassword => 'text:/managerPassword',
ldapTimeout => 'int:/ldapTimeout',
ldapVersion => 'int:/ldapVersion',
ldapRaw => 'text:/ldapRaw',
_help => 'authLDAPConnection',
},
ldapFilters => {
_nodes =>
[qw(LDAPFilter AuthLDAPFilter mailLDAPFilter)],
LDAPFilter => 'text:/LDAPFilter',
AuthLDAPFilter => 'text:/AuthLDAPFilter',
mailLDAPFilter => 'text:/mailLDAPFilter',
_help => 'authLDAPFilters',
},
ldapGroups => {
_nodes => [
qw(ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupRecursive ldapGroupAttributeNameGroup)
],
ldapGroupBase => 'text:/ldapGroupBase',
ldapGroupObjectClass => 'text:/ldapGroupObjectClass',
ldapGroupAttributeName =>
'text:/ldapGroupAttributeName',
ldapGroupAttributeNameUser =>
'text:/ldapGroupAttributeNameUser',
ldapGroupAttributeNameSearch =>
'text:/ldapGroupAttributeNameSearch',
ldapGroupRecursive => 'bool:/ldapGroupRecursive',
ldapGroupAttributeNameGroup =>
'text:/ldapGroupAttributeNameGroup',
_help => 'authLDAPGroups',
},
ldapPassword => {
_nodes => [
qw(ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue)
],
ldapPpolicyControl => 'bool:/ldapPpolicyControl',
ldapSetPassword => 'bool:/ldapSetPassword',
ldapChangePasswordAsUser =>
'bool:/ldapChangePasswordAsUser',
ldapPwdEnc => 'text:/ldapPwdEnc',
ldapUsePasswordResetAttribute =>
'bool:/ldapUsePasswordResetAttribute',
ldapPasswordResetAttribute =>
'text:/ldapPasswordResetAttribute',
ldapPasswordResetAttributeValue =>
'text:/ldapPasswordResetAttributeValue',
_help => 'authLDAPPassword',
},
},
# SSL
sslParams => {
_nodes => [qw(SSLAuthnLevel SSLVar)],
_help => 'authSSL',
SSLAuthnLevel => 'int:/SSLAuthnLevel',
SSLVar => 'text:/SSLVar',
},
# CAS
casParams => {
_nodes => [
qw(CAS_authnLevel CAS_url CAS_CAFile CAS_renew CAS_gateway CAS_pgtFile cn:CAS_proxiedServices)
],
_help => 'authCAS',
CAS_authnLevel => 'int:/CAS_authnLevel',
CAS_url => 'text:/CAS_url',
CAS_CAFile => 'text:/CAS_CAFile',
CAS_renew => 'bool:/CAS_renew',
CAS_gateway => 'bool:/CAS_gateway',
CAS_pgtFile => 'text:/CAS_pgtFile',
CAS_proxiedServices => {
_nodes => ['hash:/CAS_proxiedServices:authCAS:btext'],
_js => 'hashRoot',
_help => 'authCAS',
},
},
# Radius
radiusParams => {
_nodes => [qw(radiusAuthnLevel radiusSecret radiusServer)],
_help => 'authRadius',
radiusAuthnLevel => 'int:/radiusAuthnLevel',
radiusSecret => 'text:/radiusSecret',
radiusServer => 'text:/radiusServer',
},
# Remote
remoteParams => {
_nodes => [
qw(remotePortal remoteCookieName remoteGlobalStorage cn:remoteGlobalStorageOptions)
],
_help => 'authRemote',
remotePortal => 'text:/remotePortal',
remoteCookieName => 'text:/remoteCookieName',
remoteGlobalStorage => 'text:/remoteGlobalStorage',
remoteGlobalStorageOptions => {
_nodes =>
['hash:/remoteGlobalStorageOptions:authRemote:btext'],
_js => 'hashRoot',
_help => 'authRemote',
},
},
# Proxy
proxyParams => {
_nodes =>
[qw(soapAuthService remoteCookieName soapSessionService)],
_help => 'authProxy',
soapAuthService => 'text:/soapAuthService',
remoteCookieName => 'text:/remoteCookieName',
soapSessionService => 'text:/soapSessionService',
},
# OpenID
openIdParams => {
_nodes => [qw(openIdAuthnLevel openIdSecret openIdIDPList)],
_help => 'authOpenID',
openIdAuthnLevel => 'int:/openIdAuthnLevel',
openIdSecret => 'text:/openIdSecret',
openIdIDPList =>
'text:/openIdIDPList:authOpenID:openididplist',
},
# Google
googleParams => {
_nodes => [qw(googleAuthnLevel)],
_help => 'authGoogle',
googleAuthnLevel => 'int:/googleAuthnLevel',
},
# Facebook
facebookParams => {
_nodes =>
[qw(facebookAuthnLevel facebookAppId facebookAppSecret)],
_help => 'authFacebook',
facebookAuthnLevel => 'int:/facebookAuthnLevel',
facebookAppId => 'text:facebookAppId',
facebookAppSecret => 'text:facebookAppSecret',
},
# Twitter
twitterParams => {
_nodes => [
qw(twitterAuthnLevel twitterKey twitterSecret twitterAppName)
],
_help => 'authTwitter',
twitterAuthnLevel => 'int:/twitterAuthnLevel',
twitterKey => 'text:/twitterKey',
twitterSecret => 'text:/twitterSecret',
twitterAppName => 'text:/twitterAppName',
},
# WebID
webIDParams => {
_nodes => [qw(webIDAuthnLevel webIDWhitelist)],
_help => 'authWebID',
webIDAuthnLevel => 'int:webIDAuthnLevel',
webIDWhitelist => 'text:/webIDWhitelist',
},
# DBI
dbiParams => {
_nodes => [
qw(dbiAuthnLevel n:dbiConnection n:dbiSchema n:dbiPassword)
],
_help => 'authDBI',
dbiAuthnLevel => 'int:/dbiAuthnLevel:authDBILevel:int',
dbiConnection => {
_nodes => [qw(n:dbiConnectionAuth n:dbiConnectionUser)],
dbiConnectionAuth => {
_nodes =>
[qw(dbiAuthChain dbiAuthUser dbiAuthPassword)],
dbiAuthChain => 'text:/dbiAuthChain',
dbiAuthUser => 'text:/dbiAuthUser',
dbiAuthPassword => 'text:/dbiAuthPassword',
},
dbiConnectionUser => {
_nodes =>
[qw(dbiUserChain dbiUserUser dbiUserPassword)],
dbiUserChain => 'text:/dbiUserChain',
dbiUserUser => 'text:/dbiUserUser',
dbiUserPassword => 'text:/dbiUserPassword',
},
_help => 'authDBIConnection',
},
dbiSchema => {
_nodes => [
qw(dbiAuthTable dbiUserTable dbiAuthLoginCol dbiAuthPasswordCol dbiPasswordMailCol userPivot)
],
dbiAuthTable => 'text:/dbiAuthTable',
dbiUserTable => 'text:/dbiUserTable',
dbiAuthLoginCol => 'text:/dbiAuthLoginCol',
dbiAuthPasswordCol => 'text:/dbiAuthPasswordCol',
dbiPasswordMailCol => 'text:/dbiPasswordMailCol',
userPivot => 'text:/userPivot',
_help => 'authDBISchema',
},
dbiPassword => {
_nodes => [qw(dbiAuthPasswordHash)],
dbiAuthPasswordHash => 'text:/dbiAuthPasswordHash',
_help => 'authDBIPassword',
},
},
# Apache
apacheParams => {
_nodes => [qw(apacheAuthnLevel)],
_help => 'authApache',
apacheAuthnLevel => 'int:/apacheAuthnLevel',
},
# Null
nullParams => {
_nodes => [qw(nullAuthnLevel)],
_help => 'authNull',
nullAuthnLevel => 'int:/nullAuthnLevel',
},
# Slave
slaveParams => {
_nodes =>
[qw(slaveAuthnLevel slaveUserHeader slaveMasterIP)],
_help => 'authSlave',
slaveAuthnLevel => 'int:/slaveAuthnLevel',
slaveUserHeader => 'text:/slaveUserHeader',
slaveMasterIP => 'text:/slaveMasterIP',
},
# Choice
choiceParams => {
_nodes => [qw(authChoiceParam n:authChoiceModules)],
_help => 'authChoice',
authChoiceParam => 'text:/authChoiceParam',
authChoiceModules => {
_nodes =>
['hash:/authChoiceModules:authChoice:authChoice'],
_js => 'authChoiceRoot',
_help => 'authChoice',
},
},
# Yubikey
yubikeyParams => {
_nodes => [
qw(yubikeyAuthnLevel yubikeyClientID yubikeySecretKey yubikeyPublicIDSize)
],
_help => 'authYubikey',
yubikeyAuthnLevel => 'int:/yubikeyAuthnLevel',
yubikeyClientID => 'text:/yubikeyClientID',
yubikeySecretKey => 'text:/yubikeySecretKey',
yubikeyPublicIDSize => 'int:/yubikeyPublicIDSize',
},
# BrowserID
browserIdParams => {
_nodes => [
qw(browserIdAuthnLevel browserIdAutoLogin browserIdVerificationURL browserIdSiteName browserIdSiteLogo browserIdBackgroundColor)
],
_help => 'authBrowserID',
browserIdAuthnLevel => 'int:/browserIdAuthnLevel',
browserIdAutoLogin => 'bool:/browserIdAutoLogin',
browserIdVerificationURL =>
'text:/browserIdVerificationURL',
browserIdSiteName => 'text:/browserIdSiteName',
browserIdSiteLogo => 'text:/browserIdSiteLogo',
browserIdBackgroundColor =>
'text:/browserIdBackgroundColor',
},
},
# ISSUERDB PARAMETERS
issuerParams => {
_nodes => [qw(issuerDBSAML issuerDBCAS issuerDBOpenID)],
_help => 'issuerdb',
issuerDBSAML => {
_nodes => [
qw(issuerDBSAMLActivation issuerDBSAMLPath issuerDBSAMLRule)
],
_help => 'issuerdbSAML',
issuerDBSAMLActivation => 'bool:/issuerDBSAMLActivation',
issuerDBSAMLPath => 'text:/issuerDBSAMLPath',
issuerDBSAMLRule =>
'text:/issuerDBSAMLRule:issuerdbSAML:boolOrPerlExpr',
},
issuerDBCAS => {
_nodes => [
qw(issuerDBCASActivation issuerDBCASPath issuerDBCASRule issuerDBCASOptions)
],
_help => 'issuerdbCAS',
issuerDBCASActivation => 'bool:/issuerDBCASActivation',
issuerDBCASPath => 'text:/issuerDBCASPath',
issuerDBCASRule =>
'text:/issuerDBCASRule:issuerdbCAS:boolOrPerlExpr',
issuerDBCASOptions => {
_nodes => [
qw(casAttr casAccessControlPolicy casStorage cn:casStorageOptions)
],
casAttr => 'text:/casAttr',
casAccessControlPolicy =>
'select:/casAccessControlPolicy:issuerdbCAS:casAccessControlPolicyParams',
casStorage => 'text:/casStorage',
casStorageOptions => {
_nodes =>
['hash:/casStorageOptions:issuerDBCAS:btext'],
_js => 'hashRoot',
_help => 'issuerdbCAS',
},
},
},
issuerDBOpenID => {
_nodes => [
qw(issuerDBOpenIDActivation issuerDBOpenIDPath issuerDBOpenIDRule n:issuerDBOpenIDOptions)
],
_help => 'issuerdbOpenID',
issuerDBOpenIDActivation =>
'bool:/issuerDBOpenIDActivation',
issuerDBOpenIDPath => 'text:/issuerDBOpenIDPath',
issuerDBOpenIDRule =>
'text:/issuerDBOpenIDRule:issuerdbOpenID:boolOrPerlExpr',
issuerDBOpenIDOptions => {
_nodes => [
qw(openIdIssuerSecret openIdAttr openIdSPList n:openIdSreg)
],
openIdIssuerSecret => 'text:/openIdIssuerSecret',
openIdAttr => 'text:/openIdAttr',
openIdSPList =>
'text:/openIdSPList:issuerdbOpenID:openididplist',
openIdSreg => {
_nodes => [
qw(openIdSreg_fullname openIdSreg_nickname openIdSreg_language openIdSreg_postcode openIdSreg_timezone openIdSreg_country openIdSreg_gender openIdSreg_email openIdSreg_dob)
],
openIdSreg_fullname => 'text:openIdSreg_fullname',
openIdSreg_nickname => 'text:openIdSreg_nickname',
openIdSreg_language => 'text:openIdSreg_language',
openIdSreg_postcode => 'text:openIdSreg_postcode',
openIdSreg_timezone => 'text:openIdSreg_timezone',
openIdSreg_country => 'text:openIdSreg_country',
openIdSreg_gender => 'text:openIdSreg_gender',
openIdSreg_email => 'text:openIdSreg_email',
openIdSreg_dob => 'text:openIdSreg_dob',
},
},
},
},
# LOGS PARAMETERS
logParams => {
_nodes => [qw(syslog trustedProxies whatToTrace)],
_help => 'logs',
syslog => 'text:/syslog',
trustedProxies => 'text:/trustedProxies',
whatToTrace => 'text:/whatToTrace',
},
# COOKIE PARAMETERS
cookieParams => {
_nodes => [
qw(cookieName domain cda securedCookie httpOnly cookieExpiration)
],
_help => 'cookies',
cookieName => 'text:/cookieName',
domain => 'text:/domain',
cda => 'bool:/cda',
securedCookie =>
'select:/securedCookie:cookies:securedCookieValues',
httpOnly => 'bool:/httpOnly',
cookieExpiration => 'text:/cookieExpiration',
},
# SESSIONS PARAMETERS
sessionParams => {
_nodes => [
qw(storePassword timeout timeoutActivity cn:grantSessionRules n:sessionStorage n:multipleSessions n:persistentSessions)
],
_help => 'sessions',
storePassword => 'bool:/storePassword',
timeout => 'int:/timeout',
timeoutActivity =>
'text:/timeoutActivity:sessions:timeoutActivityParams',
grantSessionRules => {
_nodes => [
'hash:/grantSessionRules:grantSessionRules:grantSessionRules'
],
_js => 'grantSessionRulesRoot',
},
sessionStorage => {
_nodes => [qw(globalStorage cn:globalStorageOptions)],
_help => 'sessionsdb',
globalStorage => 'text:/globalStorage',
globalStorageOptions => {
_nodes =>
['hash:/globalStorageOptions:sessionsdb:btext'],
_js => 'hashRoot',
_help => 'sessionsdb',
},
},
multipleSessions => {
_nodes => [
qw(singleSession singleIP singleUserByIP notifyDeleted notifyOther)
],
singleSession => 'bool:/singleSession',
singleIP => 'bool:/singleIP',
singleUserByIP => 'bool:/singleUserByIP',
notifyDeleted => 'bool:/notifyDeleted',
notifyOther => 'bool:/notifyOther',
},
persistentSessions => {
_nodes =>
[qw(persistentStorage cn:persistentStorageOptions)],
_help => 'sessionsdb',
persistentStorage => 'text:/persistentStorage',
persistentStorageOptions => {
_nodes =>
['hash:/persistentStorageOptions:sessionsdb:btext'],
_js => 'hashRoot',
_help => 'sessionsdb',
},
},
},
# RELOAD URLS
reloadUrls => {
_nodes => ['hash:/reloadUrls:reloadUrls:btext'],
_js => 'hashRoot',
_help => 'reloadUrls',
},
# OTHER PARAMETERS
advancedParams => {
_nodes => [
qw(customFunctions n:soap n:loginHistory n:notifications n:passwordManagement n:security n:redirection n:portalRedirection n:specialHandlers cn:logoutServices)
],
_help => 'advanced',
customFunctions => 'text:/customFunctions:customfunctions:text',
soap => {
_nodes => [qw(Soap exportedAttr)],
Soap => 'bool:/Soap',
exportedAttr => 'text:/exportedAttr',
},
loginHistory => {
_nodes => [
qw(loginHistoryEnabled successLoginNumber failedLoginNumber cn:sessionDataToRemember)
],
_help => 'loginHistory',
loginHistoryEnabled => 'bool:/loginHistoryEnabled',
successLoginNumber => 'int:/successLoginNumber',
failedLoginNumber => 'int:/failedLoginNumber',
sessionDataToRemember => {
_nodes =>
['hash:/sessionDataToRemember:loginHistory:btext'],
_js => 'hashRoot',
},
},
notifications => {
_nodes => [
qw(notification notificationStorage cn:notificationStorageOptions notificationWildcard notificationXSLTfile)
],
_help => 'notifications',
notification => 'bool:/notification',
notificationStorage => 'text:/notificationStorage',
notificationStorageOptions => {
_nodes => [
'hash:/notificationStorageOptions:notifications:btext'
],
_js => 'hashRoot',
_help => 'notifications',
},
notificationWildcard => 'text:/notificationWildcard',
notificationXSLTfile => 'text:/notificationXSLTfile',
},
passwordManagement => {
_nodes => [qw(SMTP mailHeaders mailContent mailOther)],
_help => 'password',
SMTP => {
_nodes => [qw(SMTPServer SMTPAuthUser SMTPAuthPass)],
SMTPServer => 'text:/SMTPServer',
SMTPAuthUser => 'text:/SMTPAuthUser',
SMTPAuthPass => 'text:/SMTPAuthPass',
},
mailHeaders => {
_nodes => [qw(mailFrom mailReplyTo mailCharset)],
mailFrom => 'text:/mailFrom',
mailReplyTo => 'text:/mailReplyTo',
mailCharset => 'text:/mailCharset',
},
mailContent => {
_nodes => [
qw(mailSubject mailBody mailConfirmSubject mailConfirmBody)
],
mailSubject => 'text:/mailSubject',
mailBody => 'textarea:/mailBody',
mailConfirmSubject => 'text:/mailConfirmSubject',
mailConfirmBody => 'textarea:/mailConfirmBody',
},
mailOther => {
_nodes => [
qw(mailUrl randomPasswordRegexp mailTimeout mailSessionKey)
],
mailUrl => 'text:/mailUrl',
randomPasswordRegexp => 'text:/randomPasswordRegexp',
mailTimeout => 'int:/mailTimeout',
mailSessionKey => 'text:/mailSessionKey',
},
},
security => {
_nodes => [
qw(userControl portalForceAuthn key trustedDomains useSafeJail checkXSS)
],
_help => 'security',
userControl => 'text:/userControl',
portalForceAuthn => 'bool:/portalForceAuthn',
key => 'text:/key',
trustedDomains => 'text:/trustedDomains',
useSafeJail => 'bool:/useSafeJail',
checkXSS => 'bool:/checkXSS',
},
redirection => {
_nodes => [
qw(https port useRedirectOnForbidden useRedirectOnError maintenance)
],
_help => 'redirections',
https => 'bool:/https',
port => 'int:/port',
useRedirectOnForbidden => 'bool:/useRedirectOnForbidden',
useRedirectOnError => 'bool:/useRedirectOnError',
maintenance => 'bool:/maintenance',
},
portalRedirection => {
_nodes => [qw(jsRedirect)],
_help => 'portalRedirections',
jsRedirect =>
'text:/jsRedirect:portalRedirections:boolOrPerlExpr',
},
specialHandlers => {
_nodes =>
[qw(zimbraHandler sympaHandler secureTokenHandler)],
# Zimbra
zimbraHandler => {
_nodes => [
qw(zimbraPreAuthKey zimbraAccountKey zimbraBy zimbraUrl zimbraSsoUrl)
],
_help => 'zimbra',
zimbraPreAuthKey => 'text:/zimbraPreAuthKey',
zimbraAccountKey => 'text:/zimbraAccountKey',
zimbraBy => 'text:/zimbraBy:default:zimbraByParams',
zimbraUrl => 'text:/zimbraUrl',
zimbraSsoUrl => 'text:/zimbraSsoUrl',
},
# Sympa
sympaHandler => {
_nodes => [qw(sympaSecret sympaMailKey)],
_help => 'sympa',
sympaSecret => 'text:/sympaSecret',
sympaMailKey => 'text:/sympaMailKey',
},
# Secure Token
secureTokenHandler => {
_nodes => [
qw(secureTokenMemcachedServers secureTokenExpiration secureTokenAttribute secureTokenUrls secureTokenHeader secureTokenAllowOnError)
],
_help => 'securetoken',
secureTokenMemcachedServers =>
'text:/secureTokenMemcachedServers',
secureTokenExpiration => 'int:/secureTokenExpiration',
secureTokenAttribute => 'text:secureTokenAttribute',
secureTokenUrls => 'text:/secureTokenUrls',
secureTokenHeader => 'text:/secureTokenHeader',
secureTokenAllowOnError =>
'bool:/secureTokenAllowOnError',
},
},
logoutServices => {
_nodes => ['hash:/logoutServices:logoutforward:btext'],
_js => 'hashRoot',
_help => 'logoutforward',
},
},
},
#############
# VARIABLES #
#############
variables => {
_nodes => [qw(cn:exportedVars cn:macros cn:groups)],
_help => 'default',
# EXPORTED ATTRIBUTES
exportedVars => {
_nodes => ['hash:/exportedVars:vars:btext'],
_js => 'hashRoot',
_help => 'exportedVars',
},
# MACROS
macros => {
_nodes => ['hash:/macros:macros:btext'],
_js => 'hashRoot',
_help => 'macrosandgroups',
},
# GROUPS
groups => {
_nodes => ['hash:/groups:groups:btext'],
_js => 'hashRoot',
_help => 'macrosandgroups',
},
},
#################
# VIRTUAL HOSTS #
#################
virtualHosts => {
_nodes => ['nhash:/locationRules:virtualHosts:vhost'],
_upload => [qw(/exportedHeaders /post /vhostOptions)],
_help => 'virtualHosts',
_js => 'vhostRoot',
},
########
# SAML #
########
# virtual keys should not begin like configuration keys.
samlIDPMetaDataNode => {
_nodes => [
'nhash:/samlIDPMetaDataExportedAttributes:samlIDPMetaDataNode:samlIdpMetaData'
],
_upload => [ '/samlIDPMetaDataXML', '/samlIDPMetaDataOptions' ],
_help => 'samlIDP',
_js => 'samlIdpRoot',
},
samlSPMetaDataNode => {
_nodes => [
'nhash:/samlSPMetaDataExportedAttributes:samlSPMetaDataNode:samlSpMetaData'
],
_upload => [ '/samlSPMetaDataXML', '/samlSPMetaDataOptions' ],
_help => 'samlSP',
_js => 'samlSpRoot',
},
samlServiceMetaData => {
_nodes => [
qw(samlEntityID
n:samlServiceSecurity
n:samlNameIDFormatMap
n:samlAuthnContextMap
n:samlOrganization
n:samlSPSSODescriptor
n:samlIDPSSODescriptor
n:samlAttributeAuthorityDescriptor
n:samlAdvanced)
],
_help => 'samlService',
# GLOBAL INFORMATIONS
samlEntityID => 'text:/samlEntityID:samlServiceEntityID:text',
# SECURITY NODE
samlServiceSecurity => {
_nodes =>
[qw(n:samlServiceSecuritySig n:samlServiceSecurityEnc)],
_help => 'samlServiceSecurity',
samlServiceSecuritySig => {
_nodes => [
qw(samlServicePrivateKeySig
samlServicePrivateKeySigPwd
samlServicePublicKeySig)
],
samlServicePrivateKeySig =>
'filearea:/samlServicePrivateKeySig',
samlServicePrivateKeySigPwd =>
'text:/samlServicePrivateKeySigPwd',
samlServicePublicKeySig =>
'filearea:/samlServicePublicKeySig',
},
samlServiceSecurityEnc => {
_nodes => [
qw(samlServicePrivateKeyEnc
samlServicePrivateKeyEncPwd
samlServicePublicKeyEnc)
],
samlServicePrivateKeyEnc =>
'filearea:/samlServicePrivateKeyEnc',
samlServicePrivateKeyEncPwd =>
'text:/samlServicePrivateKeyEncPwd',
samlServicePublicKeyEnc =>
'filearea:/samlServicePublicKeyEnc',
},
},
# NAMEID FORMAT MAP
samlNameIDFormatMap => {
_nodes => [
qw(samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos)
],
_help => 'samlServiceNameIDFormats',
samlNameIDFormatMapEmail => 'text:/samlNameIDFormatMapEmail',
samlNameIDFormatMapX509 => 'text:/samlNameIDFormatMapX509',
samlNameIDFormatMapWindows =>
'text:/samlNameIDFormatMapWindows',
samlNameIDFormatMapKerberos =>
'text:/samlNameIDFormatMapKerberos',
},
# AUTHN CONTEXT MAP
samlAuthnContextMap => {
_nodes => [
qw(samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos)
],
_help => 'samlServiceAuthnContexts',
samlAuthnContextMapPassword =>
'int:/samlAuthnContextMapPassword',
samlAuthnContextMapPasswordProtectedTransport =>
'int:/samlAuthnContextMapPasswordProtectedTransport',
samlAuthnContextMapTLSClient =>
'int:/samlAuthnContextMapTLSClient',
samlAuthnContextMapKerberos =>
'int:/samlAuthnContextMapKerberos',
},
# ORGANIZATION
samlOrganization => {
_nodes => [
qw(samlOrganizationDisplayName
samlOrganizationName
samlOrganizationURL)
],
_help => 'samlServiceOrganization',
samlOrganizationDisplayName =>
'text:/samlOrganizationDisplayName',
samlOrganizationURL => 'text:/samlOrganizationURL',
samlOrganizationName => 'text:/samlOrganizationName',
},
# SERVICE PROVIDER
'samlSPSSODescriptor' => {
_nodes => [
qw(samlSPSSODescriptorAuthnRequestsSigned
samlSPSSODescriptorWantAssertionsSigned
n:samlSPSSODescriptorSingleLogoutService
n:samlSPSSODescriptorAssertionConsumerService
n:samlSPSSODescriptorArtifactResolutionService
)
],
_help => 'samlServiceSP',
samlSPSSODescriptorAuthnRequestsSigned =>
'bool:/samlSPSSODescriptorAuthnRequestsSigned',
samlSPSSODescriptorWantAssertionsSigned =>
'bool:/samlSPSSODescriptorWantAssertionsSigned',
samlSPSSODescriptorSingleLogoutService => {
_nodes => [
qw(samlSPSSODescriptorSingleLogoutServiceHTTPRedirect
samlSPSSODescriptorSingleLogoutServiceHTTPPost
samlSPSSODescriptorSingleLogoutServiceSOAP)
],
samlSPSSODescriptorSingleLogoutServiceHTTPRedirect =>
'samlService:/samlSPSSODescriptorSingleLogoutServiceHTTPRedirect',
samlSPSSODescriptorSingleLogoutServiceHTTPPost =>
'samlService:/samlSPSSODescriptorSingleLogoutServiceHTTPPost',
samlSPSSODescriptorSingleLogoutServiceSOAP =>
'samlService:/samlSPSSODescriptorSingleLogoutServiceSOAP',
},
samlSPSSODescriptorAssertionConsumerService => {
_nodes => [
qw(samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact
samlSPSSODescriptorAssertionConsumerServiceHTTPPost)
],
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact =>
'samlAssertion:/samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact',
samlSPSSODescriptorAssertionConsumerServiceHTTPPost =>
'samlAssertion:/samlSPSSODescriptorAssertionConsumerServiceHTTPPost',
},
samlSPSSODescriptorArtifactResolutionService => {
_nodes => [
qw(samlSPSSODescriptorArtifactResolutionServiceArtifact)
],
samlSPSSODescriptorArtifactResolutionServiceArtifact =>
'samlAssertion:/samlSPSSODescriptorArtifactResolutionServiceArtifact',
},
},
# IDENTITY PROVIDER
samlIDPSSODescriptor => {
_nodes => [
qw(samlIDPSSODescriptorWantAuthnRequestsSigned
n:samlIDPSSODescriptorSingleSignOnService
n:samlIDPSSODescriptorSingleLogoutService
n:samlIDPSSODescriptorArtifactResolutionService)
],
_help => 'samlServiceIDP',
samlIDPSSODescriptorWantAuthnRequestsSigned =>
'bool:/samlIDPSSODescriptorWantAuthnRequestsSigned',
samlIDPSSODescriptorSingleSignOnService => {
_nodes => [
qw(samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect
samlIDPSSODescriptorSingleSignOnServiceHTTPPost
samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact
samlIDPSSODescriptorSingleSignOnServiceSOAP)
],
samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect =>
'samlService:/samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect',
samlIDPSSODescriptorSingleSignOnServiceHTTPPost =>
'samlService:/samlIDPSSODescriptorSingleSignOnServiceHTTPPost',
samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact =>
'samlService:/samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact',
samlIDPSSODescriptorSingleSignOnServiceSOAP =>
'samlService:/samlIDPSSODescriptorSingleSignOnServiceSOAP',
},
samlIDPSSODescriptorSingleLogoutService => {
_nodes => [
qw(samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect
samlIDPSSODescriptorSingleLogoutServiceHTTPPost
samlIDPSSODescriptorSingleLogoutServiceSOAP)
],
samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect =>
'samlService:/samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect',
samlIDPSSODescriptorSingleLogoutServiceHTTPPost =>
'samlService:/samlIDPSSODescriptorSingleLogoutServiceHTTPPost',
samlIDPSSODescriptorSingleLogoutServiceSOAP =>
'samlService:/samlIDPSSODescriptorSingleLogoutServiceSOAP',
},
samlIDPSSODescriptorArtifactResolutionService => {
_nodes => [
qw(samlIDPSSODescriptorArtifactResolutionServiceArtifact)
],
samlIDPSSODescriptorArtifactResolutionServiceArtifact =>
'samlAssertion:/samlIDPSSODescriptorArtifactResolutionServiceArtifact',
},
},
# ATTRIBUTE AUTHORITY
samlAttributeAuthorityDescriptor => {
_nodes =>
[qw(n:samlAttributeAuthorityDescriptorAttributeService)],
_help => 'samlServiceAA',
samlAttributeAuthorityDescriptorAttributeService => {
_nodes => [
qw(samlAttributeAuthorityDescriptorAttributeServiceSOAP)
],
samlAttributeAuthorityDescriptorAttributeServiceSOAP =>
'samlService:/samlAttributeAuthorityDescriptorAttributeServiceSOAP',
},
},
# ADVANCED SAML PARAMETERS
samlAdvanced => {
_nodes => [
qw(samlIdPResolveCookie samlMetadataForceUTF8 samlStorage cn:samlStorageOptions n:samlCommonDomainCookie)
],
_help => 'samlServiceAdvanced',
samlIdPResolveCookie => 'text:/samlIdPResolveCookie',
samlMetadataForceUTF8 => 'bool:/samlMetadataForceUTF8',
samlStorage => 'text:/samlStorage',
samlStorageOptions => {
_nodes =>
['hash:/samlStorageOptions:samlServiceAdvanced:btext'],
_js => 'hashRoot',
_help => 'samlServiceAdvanced',
},
samlCommonDomainCookie => {
_nodes => [
qw(samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter)
],
samlCommonDomainCookieActivation =>
'bool:/samlCommonDomainCookieActivation',
samlCommonDomainCookieDomain =>
'text:/samlCommonDomainCookieDomain',
samlCommonDomainCookieReader =>
'text:/samlCommonDomainCookieReader',
samlCommonDomainCookieWriter =>
'text:/samlCommonDomainCookieWriter',
},
},
},
};
}
## @method protected hashref testStruct()
# Returns the tests to do with the datas uploaded.
# @return hashref
sub testStruct {
my $safe = Safe->new();
my $perlExpr = sub {
my $e = shift;
$safe->reval( $e, 1 );
return 1 unless ($@);
return 1
if ( $@ =~ /Global symbol "\$.*requires explicit package/ );
return ( 1,
"Function \"$1$2\" must be declared in customFunctions" )
if ( $@ =~
/(?:Bareword "(\w+)" not allowed while "strict subs"|Undefined subroutine &(?:.*?::)?(\w+))/
);
return ( 0, $@ );
};
my $noAssign = sub {
my $e = shift;
my $assignTest = qr/(?<=[^=\|\?])=(?![=~])/;
return $e =~ $assignTest ? ( 0, "contains an assignment" ) : 1;
};
my $boolean = { test => qr/^(?:0|1)?$/, msgFail => 'Value must be 0 or 1' };
my $integer =
{ test => qr/^(?:\d)+$/, msgFail => 'Value must be an integer' };
my $pcre = sub {
my $r = shift;
my $q;
eval { $q = qr/$r/ };
return ( $@ ? ( 0, $@ ) : 1 );
};
my $domainNameOrIp = sub {
my $n = shift;
return
$n =~ /^(\d{1,3}\.){3}\d{1,3}$/
|| $n =~ Lemonldap::NG::Common::Regexp::HOSTNAME()
|| ( 0, 'Bad server name or IP' );
};
my $testNotDefined = { test => sub { 1 }, msgFail => 'Ok' };
my $lmAttrOrMacro = {
test => qr/^\$?[a-zA-Z_]\w*$/,
msgFail => 'Value must be in the form $attr'
};
return {
applicationList => {
keyTest => qr/^(\d*)?\w+$/,
keyMsgFail => 'Bad category ID',
},
mailCharset => $testNotDefined,
mailFrom => $testNotDefined,
mailReplyTo => $testNotDefined,
trustedDomains => $testNotDefined,
exportedAttr => $testNotDefined,
mailSubject => $testNotDefined,
randomPasswordRegexp => $testNotDefined,
passwordDB => $testNotDefined,
mailBody => $testNotDefined,
SMTPServer => $testNotDefined,
SMTPAuthUser => $testNotDefined,
SMTPAuthPass => $testNotDefined,
cookieExpiration => $testNotDefined,
notificationStorage => $testNotDefined,
notificationWildcard => $testNotDefined,
notificationXSLTfile => $testNotDefined,
mailUrl => $testNotDefined,
mailTimeout => $integer,
mailSessionKey => $testNotDefined,
mailConfirmSubject => $testNotDefined,
mailConfirmBody => $testNotDefined,
authentication => {
test => sub {
my $e = shift;
# Do not check syntax for Multi
return 1 if ( $e =~ /^multi/i );
# Else, check the authentication module is valid
return ( $e =~ qr/^[a-zA-Z]+$/ );
},
msgFail => 'Bad module name',
},
captcha_login_enabled => $boolean,
captcha_mail_enabled => $boolean,
captcha_size => $integer,
captcha_data => $testNotDefined,
captcha_output => $testNotDefined,
cda => $boolean,
checkXSS => $boolean,
cookieName => {
test => qr/^[a-zA-Z]\w*$/,
msgFail => 'Bad cookie name',
},
customFunctions => $testNotDefined,
domain => {
test => qr/^\.?[\w\-]+(?:\.[a-zA-Z][\w\-]*)*(?:\.[a-zA-Z]+)$/,
msgFail => 'Bad domain',
},
exportedHeaders => {
keyTest => Lemonldap::NG::Common::Regexp::HOSTNAME(),
keyMsgFail => 'Bad virtual host name',
'*' => {
keyTest => qr/^\w([\w\-]*\w)?$/,
keyMsgFail => 'Bad header name',
test => $perlExpr,
warnTest => $noAssign,
},
},
exportedVars => {
keyTest => qr/^!?[a-zA-Z][\w-]*$/,
keyMsgFail => 'Bad variable name',
test => qr/^[a-zA-Z][\w:\-]*$/,
msgFail => 'Bad attribute name',
},
failedLoginNumber => $integer,
globalStorage => {
test => qr/^[\w:]+$/,
msgFail => 'Bad module name',
},
globalStorageOptions => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad parameter',
},
grantSessionRules => {
keyTest => $perlExpr,
warnKeyTest => $noAssign,
},
groups => {
keyTest => qr/^\w[\w-]*$/,
keyMsgFail => 'Bad group name',
test => $perlExpr,
warnTest => $noAssign,
},
httpOnly => $boolean,
https => $boolean,
issuerDBSAMLActivation => $boolean,
issuerDBSAMLPath => $testNotDefined,
issuerDBSAMLRule => {
test => $perlExpr,
warnTest => $noAssign,
},
issuerDBCASActivation => $boolean,
issuerDBCASPath => $testNotDefined,
issuerDBCASRule => {
test => $perlExpr,
warnTest => $noAssign,
},
issuerDBOpenIDActivation => $boolean,
issuerDBOpenIDPath => $testNotDefined,
issuerDBOpenIDRule => {
test => $perlExpr,
warnTest => $noAssign,
},
jsRedirect => { test => $perlExpr, },
key => $testNotDefined,
ldapAuthnLevel => $integer,
ldapBase => {
test => qr/^(?:\w+=.*|)$/,
msgFail => 'Bad LDAP base',
},
ldapPort => {
test => qr/^\d*$/,
msgFail => 'Bad port number'
},
ldapServer => {
test => sub {
my $l = shift;
my @s = split( /[\s,]+/, $l );
foreach my $s (@s) {
$s =~
m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?::\d{1,5})?/?.*)$}o
or return ( 0, "Bad ldap uri \"$s\"" );
}
return 1;
},
},
ldapPwdEnc => {
test => qr/^\w[\w\-]*\w$/,
msgFail => 'Bad encoding',
},
ldapUsePasswordResetAttribute => $boolean,
ldapPasswordResetAttribute => $testNotDefined,
ldapPasswordResetAttributeValue => $testNotDefined,
ldapPpolicyControl => $boolean,
ldapSetPassword => $boolean,
ldapChangePasswordAsUser => $boolean,
mailLDAPFilter => $testNotDefined,
LDAPFilter => $testNotDefined,
AuthLDAPFilter => $testNotDefined,
ldapGroupRecursive => $boolean,
ldapGroupObjectClass => $testNotDefined,
ldapGroupBase => $testNotDefined,
ldapGroupAttributeName => $testNotDefined,
ldapGroupAttributeNameUser => $testNotDefined,
ldapGroupAttributeNameSearch => $testNotDefined,
ldapGroupAttributeNameGroup => $testNotDefined,
ldapTimeout => $testNotDefined,
ldapVersion => $testNotDefined,
ldapRaw => $testNotDefined,
locationRules => {
keyTest => Lemonldap::NG::Common::Regexp::HOSTNAME(),
msgFail => 'Bad virtual host name',
'*' => {
keyTest => $pcre,
test => sub {
my $e = shift;
return 1 if ( $e =~ /^(?:accept|deny|unprotect|skip)$/i );
if ( $e =~ s/^logout(?:_(?:app_sso|app|sso))?\s*// ) {
return (
$e eq ''
or $e =~ Lemonldap::NG::Common::Regexp::HTTP_URI()
? 1
: ( 0, "bad url \"$e\"" )
);
}
return &$perlExpr($e);
},
warnTest => $noAssign,
},
},
loginHistoryEnabled => $boolean,
logoutServices => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad name',
},
macros => {
keyTest => qr/^[_a-zA-Z]\w*$/,
keyMsgFail => 'Bad macro name',
test => $perlExpr,
warnTest => $noAssign,
},
mailOnPasswordChange => $boolean,
maintenance => $boolean,
managerDn => {
test => qr/^(?:\w+=.*)?$/,
msgFail => 'Bad LDAP dn',
},
managerPassword => {
test => qr/^\S*$/,
msgFail => 'Bad LDAP password',
},
notification => $boolean,
notificationStorage => {
test => qr/^[\w:]+$/,
msgFail => 'Bad module name',
},
notificationStorageOptions => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad parameter',
},
notifyDeleted => $boolean,
notifyOther => $boolean,
persistentStorageOptions => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad parameter',
},
port => {
test => qr/^\d*$/,
msgFail => 'Bad port number'
},
portal => {
test => qr/^https?:\/\/\S+$/,
msgFail => 'Bad portal value',
},
portalAutocomplete => $boolean,
portalCheckLogins => $boolean,
portalDisplayLoginHistory => { test => $perlExpr, },
portalDisplayAppslist => { test => $perlExpr, },
portalDisplayChangePassword => { test => $perlExpr, },
portalDisplayLogout => { test => $perlExpr, },
portalDisplayResetPassword => $boolean,
portalForceAuthn => $boolean,
portalOpenLinkInNewWindow => $boolean,
portalAntiFrame => $boolean,
portalParams => $testNotDefined,
portalRequireOldPassword => $boolean,
hideOldPassword => $boolean,
portalSkin => {
test => qr/\w+$/,
msgFail => 'Bad skin name',
},
portalSkinRules => {
keyTest => $perlExpr,
keyMsgFail => 'Bad skin rule',
test => qr/\w+$/,
msgFail => 'Bad skin name',
},
portalUserAttr => {
test => qr/\w+$/,
msgFail => 'Unvalid session field',
},
post => {
keyTest => Lemonldap::NG::Common::Regexp::HOSTNAME(),
keyMsgFail => 'Bad virtual host name',
'*' => { keyTest => $pcre, },
},
protection => {
keyTest => qr/^(?:none|authentificate|manager|)$/,
msgFail => 'must be one of none authentificate manager',
},
reloadUrls => {
keyTest => $domainNameOrIp,
test => Lemonldap::NG::Common::Regexp::HTTP_URI(),
msgFail => 'Bad url'
},
securedCookie => {
test => qr/^(?:0|1|2|3)$/,
msgFail => 'securedCookie must be 0, 1, 2 or 3',
},
sessionDataToRemember => {
keyTest => qr/^[\w-]+$/,
keyMsgFail => 'Invalid session data',
},
singleSession => $boolean,
singleIP => $boolean,
singleUserByIP => $boolean,
slaveMasterIP => {
test =>
qr/^(\s*((\d{1,3}\.){3}\d{1,3}\s+)*(\d{1,3}\.){3}\d{1,3})?\s*$/,
msgFail => 'Bad parameter "master\'s IP" in Slave',
},
Soap => $boolean,
storePassword => $boolean,
successLoginNumber => $integer,
syslog => {
test => qw/^(?:auth|authpriv|daemon|local\d|user)?$/,
msgFail =>
'Only auth|authpriv|daemon|local0-7|user is allowed here',
},
timeout => {
test => qr/^\d*$/,
msgFail => 'Bad number'
},
timeoutActivity => {
test => qr/^\d*$/,
msgFail => 'Bad number',
},
trustedProxies => $testNotDefined,
userControl => {
test => $pcre,
msgFail => 'Bad regular expression',
},
userDB => {
test => qr/^[a-zA-Z][\w\:]*$/,
msgFail => 'Bad module name',
},
useRedirectOnError => $boolean,
useRedirectOnForbidden => $boolean,
useSafeJail => $boolean,
variables => $testNotDefined,
vhostOptions => {
keyTest => Lemonldap::NG::Common::Regexp::HOSTNAME(),
keyMsgFail => 'Bad virtual host name',
'*' => {
keyTest => qr/^vhost(Port|Https|Maintenance|Aliases)$/,
keyMsgFail => 'Bad option name',
},
},
whatToTrace => $lmAttrOrMacro,
########
# SAML #
########
saml => $testNotDefined,
samlServiceMetaData => $testNotDefined,
samlIDPMetaDataExportedAttributes => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
keyTest => qr/^\w([\w\-]*\w)?$/,
keyMsgFail => 'Bad attribute name',
test => sub { return 1; },
},
},
samlIDPMetaDataXML => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
samlIDPMetaDataOptions => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
samlSPMetaDataExportedAttributes => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
keyTest => qr/^\w([\w\-]*\w)?$/,
keyMsgFail => 'Bad attribute name',
test => sub { return 1; },
},
},
samlSPMetaDataXML => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
samlSPMetaDataOptions => {
keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
keyMsgFail => 'Bad metadata name',
'*' => {
test => sub { return 1; },
keyTest => sub { return 1; },
},
},
samlEntityID => $testNotDefined,
samlOrganizationDisplayName => $testNotDefined,
samlOrganizationName => $testNotDefined,
samlOrganizationURL => $testNotDefined,
samlSPSSODescriptorAuthnRequestsSigned => $boolean,
samlSPSSODescriptorWantAssertionsSigned => $boolean,
samlSPSSODescriptorSingleLogoutServiceHTTPRedirect => $testNotDefined,
samlSPSSODescriptorSingleLogoutServiceHTTPPost => $testNotDefined,
samlSPSSODescriptorSingleLogoutServiceSOAP => $testNotDefined,
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact =>
$testNotDefined,
samlSPSSODescriptorAssertionConsumerServiceHTTPPost => $testNotDefined,
samlSPSSODescriptorArtifactResolutionServiceArtifact => $testNotDefined,
samlIDPSSODescriptorWantAuthnRequestsSigned => $boolean,
samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect => $testNotDefined,
samlIDPSSODescriptorSingleSignOnServiceHTTPPost => $testNotDefined,
samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact => $testNotDefined,
samlIDPSSODescriptorSingleSignOnServiceSOAP => $testNotDefined,
samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect => $testNotDefined,
samlIDPSSODescriptorSingleLogoutServiceHTTPPost => $testNotDefined,
samlIDPSSODescriptorSingleLogoutServiceSOAP => $testNotDefined,
samlIDPSSODescriptorArtifactResolutionServiceArtifact =>
$testNotDefined,
samlNameIDFormatMapEmail => $testNotDefined,
samlNameIDFormatMapX509 => $testNotDefined,
samlNameIDFormatMapWindows => $testNotDefined,
samlNameIDFormatMapKerberos => $testNotDefined,
samlAttributeAuthorityDescriptorAttributeServiceSOAP => $testNotDefined,
samlServicePrivateKeySig => $testNotDefined,
samlServicePrivateKeySigPwd => $testNotDefined,
samlServicePublicKeySig => $testNotDefined,
samlServicePrivateKeyEnc => $testNotDefined,
samlServicePrivateKeyEncPwd => $testNotDefined,
samlServicePublicKeyEnc => $testNotDefined,
samlIdPResolveCookie => $testNotDefined,
samlMetadataForceUTF8 => $boolean,
samlStorage => {
test => qr/^[\w:]*$/,
msgFail => 'Bad module name',
},
samlStorageOptions => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad parameter',
},
samlAuthnContextMapPassword => $integer,
samlAuthnContextMapPasswordProtectedTransport => $integer,
samlAuthnContextMapTLSClient => $integer,
samlAuthnContextMapKerberos => $integer,
samlCommonDomainCookieActivation => $boolean,
samlCommonDomainCookieDomain => {
test => Lemonldap::NG::Common::Regexp::HOSTNAME(),
msgFail => 'Bad domain',
},
samlCommonDomainCookieReader => {
test => Lemonldap::NG::Common::Regexp::HTTP_URI(),
msgFail => 'Bad URI',
},
samlCommonDomainCookieWriter => {
test => Lemonldap::NG::Common::Regexp::HTTP_URI(),
msgFail => 'Bad URI',
},
# SSL
SSLAuthnLevel => $integer,
SSLVar => $testNotDefined,
# CAS
CAS_authnLevel => $integer,
CAS_url => {
test => Lemonldap::NG::Common::Regexp::HTTP_URI(),
msgFail => 'Bad CAS url',
},
CAS_CAFile => $testNotDefined,
CAS_renew => $boolean,
CAS_gateway => $boolean,
CAS_pgtFile => $testNotDefined,
CAS_proxiedServices => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad CAS proxied service identifier',
},
casAttr => $testNotDefined,
casAccessControlPolicy => $testNotDefined,
casStorage => {
test => qr/^[\w:]*$/,
msgFail => 'Bad module name',
},
casStorageOptions => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad parameter',
},
# Radius
radiusAuthnLevel => $integer,
radiusSecret => $testNotDefined,
radiusServer => $testNotDefined,
# Remote
remotePortal => $testNotDefined,
remoteGlobalStorage => {
test => qr/^[\w:]+$/,
msgFail => 'Bad module name',
},
remoteGlobalStorageOptions => {
keyTest => qr/^\w+$/,
keyMsgFail => 'Bad parameter',
},
# Proxy
soapAuthService => $testNotDefined,
remoteCookieName => $testNotDefined,
soapSessionService => $testNotDefined,
# OpenID
openIdAuthnLevel => $integer,
openIdSecret => $testNotDefined,
# Google
googleAuthnLevel => $integer,
# Facebook
facebookAuthnLevel => $integer,
facebookAppId => $testNotDefined,
facebookAppSecret => $testNotDefined,
# Twitter
twitterAuthnLevel => $integer,
twitterKey => $testNotDefined,
twitterSecret => $testNotDefined,
twitterAppName => $testNotDefined,
# WebID
webIDAuthnLevel => $integer,
webIDWhitelist => $testNotDefined,
# DBI
dbiAuthnLevel => $integer,
dbiAuthChain => $testNotDefined,
dbiAuthUser => $testNotDefined,
dbiAuthPassword => $testNotDefined,
dbiUserChain => $testNotDefined,
dbiUserUser => $testNotDefined,
dbiUserPassword => $testNotDefined,
dbiAuthTable => $testNotDefined,
dbiUserTable => $testNotDefined,
dbiAuthLoginCol => $testNotDefined,
dbiAuthPasswordCol => $testNotDefined,
dbiPasswordMailCol => $testNotDefined,
userPivot => $testNotDefined,
dbiAuthPasswordHash => $testNotDefined,
# Apache
apacheAuthnLevel => $integer,
# Null
nullAuthnLevel => $integer,
# Slave
slaveAuthnLevel => $integer,
slaveUserHeader => $testNotDefined,
# Choice
authChoiceParams => $testNotDefined,
authChoiceModules => {
keyTest => qr/^(\d*)?\w+$/,
keyMsgFail => 'Bad choice key',
},
# Zimbra
zimbraPreAuthKey => $testNotDefined,
zimbraAccountKey => $testNotDefined,
zimbraBy => $testNotDefined,
zimbraUrl => $testNotDefined,
zimbraSsoUrl => $testNotDefined,
# Sympa
sympaSecret => $testNotDefined,
sympaMailKey => $testNotDefined,
# OpenID Issuer
openIdIssuerSecret => $testNotDefined,
openIdAttr => $testNotDefined,
openIdSreg_fullname => $lmAttrOrMacro,
openIdSreg_nickname => $lmAttrOrMacro,
openIdSreg_language => $lmAttrOrMacro,
openIdSreg_postcode => $lmAttrOrMacro,
openIdSreg_timezone => $lmAttrOrMacro,
openIdSreg_country => $lmAttrOrMacro,
openIdSreg_gender => $lmAttrOrMacro,
openIdSreg_email => $lmAttrOrMacro,
openIdSreg_dob => $lmAttrOrMacro,
# Yubikey
yubikeyAuthnLevel => $integer,
yubikeyClientID => $testNotDefined,
yubikeySecretKey => $testNotDefined,
yubikeyPublicIDSize => $integer,
# Secure Token
secureTokenMemcachedServers => $testNotDefined,
secureTokenExpiration => $integer,
secureTokenAttribute => $testNotDefined,
secureTokenUrls => $testNotDefined,
secureTokenHeader => $testNotDefined,
secureTokenAllowOnError => $boolean,
# BrowserID
browserIdAuthnLevel => $integer,
browserIdAutoLogin => $boolean,
browserIdVerificationURL => $testNotDefined,
browserIdSiteName => $testNotDefined,
browserIdSiteLogo => $testNotDefined,
browserIdBackgroundColor => $testNotDefined,
};
}
## @method protected hashref defaultConf()
#@return Hashref of default values
sub defaultConf {
my $self = shift;
return {
applicationList => {
'default' => { catname => 'Default category', type => "category" }
},
authentication => 'LDAP',
authChoiceParam => 'lmAuth',
captcha_login_enabled => '0',
captcha_mail_enabled => '0',
captcha_size => '6',
captcha_data => '/var/lib/lemonldap-ng/captcha/data',
captcha_output => '/var/lib/lemonldap-ng/portal/captcha_output',
CAS_pgtFile => '/tmp/pgt.txt',
casAccessControlPolicy => 'none',
cda => '0',
checkXSS => '1',
cookieName => 'lemonldap',
domain => 'example.com',
failedLoginNumber => '5',
globalStorage => 'Apache::Session::File',
hideOldPassword => '0',
httpOnly => '1',
https => '0',
issuerDBSAMLActivation => '0',
issuerDBSAMLPath => '^/saml/',
issuerDBSAMLRule => '1',
issuerDBCASActivation => '0',
issuerDBCASPath => '^/cas/',
issuerDBCASRule => '1',
issuerDBOpenIDActivation => '0',
issuerDBOpenIDPath => '^/openidserver/',
issuerDBOpenIDRule => '1',
jsRedirect => '0',
key => join( '', map { chr( int( rand(94) ) + 33 ) } ( 1 .. 16 ) ),
ldapBase => 'dc=example,dc=com',
ldapPort => '389',
ldapPwdEnc => 'utf-8',
ldapUsePasswordResetAttribute => '1',
ldapPasswordResetAttribute => 'pwdReset',
ldapPasswordResetAttributeValue => 'TRUE',
ldapServer => 'localhost',
ldapTimeout => '120',
ldapVersion => '3',
mailCharset => 'utf-8',
mailOnPasswordChange => '0',
maintenance => '0',
mailTimeout => '0',
mailSessionKey => 'mail',
managerDn => '',
managerPassword => '',
notification => '0',
notificationStorage => 'File',
notificationWildcard => 'allusers',
notifyDeleted => '1',
notifyOther => '0',
openIdSreg_fullname => 'cn',
openIdSreg_nickname => 'uid',
openIdSreg_timezone => '_timezone',
openIdSreg_email => 'mail',
portal => 'http://auth.example.com',
portalSkin => 'pastel',
portalUserAttr => '_user',
portalCheckLogins => '1',
portalDisplayLoginHistory => '1',
portalDisplayAppslist => '1',
portalDisplayChangePassword => '$_auth eq "LDAP" or $_auth eq "DBI"',
portalDisplayLogout => '1',
portalDisplayResetPassword => '1',
portalAntiFrame => '1',
protection => 'none',
radiusAuthnLevel => '3',
remoteGlobalStorage => 'Lemonldap::NG::Common::Apache::Session::SOAP',
securedCookie => '0',
secureTokenMemcachedServers => '127.0.0.1:11211',
secureTokenExpiration => '60',
secureTokenAttribute => 'uid',
secureTokenUrls => '.*',
secureTokenHeader => 'Auth-Token',
secureTokenAllowOnError => '1',
singleSession => '0',
singleIP => '0',
singleUserByIP => '0',
Soap => '1',
storePassword => '0',
successLoginNumber => '5',
syslog => '',
timeout => '72000',
timeoutActivity => '0',
trustedProxies => '',
userControl => '^[\w\.\-@]+$',
userDB => 'LDAP',
passwordDB => 'LDAP',
useRedirectOnError => '1',
useRedirectOnForbidden => '0',
useSafeJail => '1',
vhostPort => '-1',
vhostHttps => '-1',
vhostMaintenance => '0',
whatToTrace => '$_whatToTrace',
yubikeyPublicIDSize => '12',
########
# SAML #
########
samlEntityID => '#PORTAL#' . '/saml/metadata',
samlOrganizationDisplayName => 'Example',
samlOrganizationName => 'Example',
samlOrganizationURL => 'http://www.example.com',
samlIDPMetaDataOptionsNameIDFormat => '',
samlIDPMetaDataOptionsForceAuthn => '0',
samlIDPMetaDataOptionsIsPassive => '0',
samlIDPMetaDataOptionsAllowProxiedAuthn => '1',
samlIDPMetaDataOptionsSSOBinding => '',
samlIDPMetaDataOptionsSLOBinding => '',
samlIDPMetaDataOptionsResolutionRule => '',
samlIDPMetaDataOptionsAllowLoginFromIDP => '1',
samlIDPMetaDataOptionsAdaptSessionUtime => '1',
samlIDPMetaDataOptionsSignSSOMessage => '1',
samlIDPMetaDataOptionsCheckSSOMessageSignature => '1',
samlIDPMetaDataOptionsSignSLOMessage => '1',
samlIDPMetaDataOptionsCheckSLOMessageSignature => '1',
samlIDPMetaDataOptionsRequestedAuthnContext => '',
samlIDPMetaDataOptionsForceUTF8 => '0',
samlIDPMetaDataOptionsEncryptionMode => 'none',
samlIDPMetaDataOptionsCheckConditions => '1',
samlSPMetaDataOptionsNameIDFormat => '',
samlSPMetaDataOptionsOneTimeUse => '0',
samlSPMetaDataOptionsSignSSOMessage => '1',
samlSPMetaDataOptionsCheckSSOMessageSignature => '1',
samlSPMetaDataOptionsSignSLOMessage => '1',
samlSPMetaDataOptionsCheckSLOMessageSignature => '1',
samlSPMetaDataOptionsEncryptionMode => 'none',
samlSPSSODescriptorAuthnRequestsSigned => '1',
samlSPSSODescriptorWantAssertionsSigned => '1',
samlSPSSODescriptorSingleLogoutServiceHTTPRedirect =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
. '#PORTAL#'
. '/saml/proxySingleLogout;'
. '#PORTAL#'
. '/saml/proxySingleLogoutReturn',
samlSPSSODescriptorSingleLogoutServiceHTTPPost =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
. '#PORTAL#'
. '/saml/proxySingleLogout;'
. '#PORTAL#'
. '/saml/proxySingleLogoutReturn',
samlSPSSODescriptorSingleLogoutServiceSOAP =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
. '#PORTAL#'
. '/saml/proxySingleLogoutSOAP;',
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
. '#PORTAL#'
. '/saml/proxySingleSignOnArtifact',
samlSPSSODescriptorAssertionConsumerServiceHTTPPost =>
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
. '#PORTAL#'
. '/saml/proxySingleSignOnPost',
samlSPSSODescriptorArtifactResolutionServiceArtifact =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
. '#PORTAL#'
. '/saml/artifact',
samlIDPSSODescriptorWantAuthnRequestsSigned => '1',
samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
. '#PORTAL#'
. '/saml/singleSignOn;',
samlIDPSSODescriptorSingleSignOnServiceHTTPPost =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
. '#PORTAL#'
. '/saml/singleSignOn;',
samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
. '#PORTAL#'
. '/saml/singleSignOnArtifact;',
samlIDPSSODescriptorSingleSignOnServiceSOAP =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
. '#PORTAL#'
. '/saml/singleSignOnSOAP;',
samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
. '#PORTAL#'
. '/saml/singleLogout;'
. '#PORTAL#'
. '/saml/singleLogoutReturn',
samlIDPSSODescriptorSingleLogoutServiceHTTPPost =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
. '#PORTAL#'
. '/saml/singleLogout;'
. '#PORTAL#'
. '/saml/singleLogoutReturn',
samlIDPSSODescriptorSingleLogoutServiceSOAP =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
. '#PORTAL#'
. '/saml/singleLogoutSOAP;',
samlIDPSSODescriptorArtifactResolutionServiceArtifact =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
. '#PORTAL#'
. '/saml/artifact',
samlNameIDFormatMapEmail => 'mail',
samlNameIDFormatMapX509 => 'mail',
samlNameIDFormatMapWindows => 'uid',
samlNameIDFormatMapKerberos => 'uid',
samlAttributeAuthorityDescriptorAttributeServiceSOAP =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
. '#PORTAL#'
. '/saml/AA/SOAP;',
samlServicePrivateKeySig => '',
samlServicePrivateKeySigPwd => '',
samlServicePublicKeySig => '',
samlServicePrivateKeyEnc => '',
samlServicePrivateKeyEncPwd => '',
samlServicePublicKeyEnc => '',
samlMetadataForceUTF8 => 1,
samlAuthnContextMapPassword => 2,
samlAuthnContextMapPasswordProtectedTransport => 3,
samlAuthnContextMapTLSClient => 5,
samlAuthnContextMapKerberos => 4,
samlCommonDomainCookieActivation => 0,
# Authentication levels
ldapAuthnLevel => 2,
dbiAuthnLevel => 2,
SSLAuthnLevel => 5,
CAS_authnLevel => 1,
googleAuthnLevel => 1,
openIdAuthnLevel => 1,
facebookAuthnLevel => 1,
twitterAuthnLevel => 1,
webIDAuthnLevel => 1,
apacheAuthnLevel => 4,
nullAuthnLevel => 0,
slaveAuthnLevel => 2,
yubikeyAuthnLevel => 3,
browserIdAuthnLevel => 1,
};
}
sub subDefaultConf {
return {
exportedHeaders => { 'Auth-User' => '$uid' },
exportedVars => { cn => 'cn', mail => 'mail', uid => 'uid', },
globalStorageOptions => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
},
locationRules => { default => 'deny' },
macros => {
'_whatToTrace' =>
'$_auth eq "SAML" ? "$_user\\@$_idpConfKey" : "$_user"'
},
notificationStorageOptions =>
{ dirName => '/var/lib/lemonldap-ng/notifications', },
post => { none => { expr => {}, }, },
remoteGlobalStorageOptions => {
'proxy' => 'https://remote/index.pl/sessions',
'ns' => 'https://remote/Lemonldap/NG/Common/CGI/SOAPService',
},
samlIDPMetaDataExportedAttributes => { 'uid' => '0;uid;;' },
samlSPMetaDataExportedAttributes => { 'uid' => '0;uid;;' },
};
}
## @method hashref globalTests(hashref conf)
# Return a hash ref where keys are the names of the tests and values
# subroutines to execute.
#
# Subroutines can return one of the followings :
# - (1) : everything is OK
# - (1,message) : OK with a warning
# - (0,message) : NOK
# - (-1,message) : OK, but must be confirmed (ignored if confirm parameter is
# set
#
# Those subroutines can also modify configuration.
#
# @param $conf Configuration to test
# @return hash ref where keys are the names of the tests and values
sub globalTests {
my ( $self, $conf ) = splice @_;
return {
# 1. CHECKS
# Check if portal is in domain
portalIsInDomain => sub {
return (
1,
(
index( $conf->{portal}, $conf->{domain} ) > 0
? ''
: "Portal seems not to be in the domain $conf->{domain}"
)
);
},
# Check if virtual hosts are in the domain
vhostInDomainOrCDA => sub {
return 1 if ( $conf->{cda} );
my @pb;
foreach my $vh ( keys %{ $conf->{locationRules} } ) {
push @pb, $vh unless ( index( $vh, $conf->{domain} ) >= 0 );
}
return (
1,
(
@pb
? 'Virtual hosts '
. join( ', ', @pb )
. " are not in $conf->{domain} and cross-domain-authentication is not set"
: undef
)
);
},
# Check if virtual host do not contain a port
vhostWithPort => sub {
my @pb;
foreach my $vh ( keys %{ $conf->{locationRules} } ) {
push @pb, $vh if ( $vh =~ /:/ );
}
if (@pb) {
return ( 0,
'Virtual hosts '
. join( ', ', @pb )
. " contain a port, this is not allowed" );
}
else { return 1; }
},
# Force vhost to be lowercase
vhostUpperCase => sub {
my @pb;
foreach my $vh ( keys %{ $conf->{locationRules} } ) {
push @pb, $vh if ( $vh ne lc $vh );
}
if (@pb) {
return ( 0,
'Virtual hosts '
. join( ', ', @pb )
. " must be in lower case" );
}
else { return 1; }
},
# Check if "userDB" and "authentication" are consistent
authAndUserDBConsistency => sub {
foreach my $type (qw(Facebook Google OpenID SAML WebID)) {
return ( 0,
"\"$type\" can not be used as user database without using \"$type\" for authentication"
)
if ( $conf->{userDB} =~ /$type/
and $conf->{authentication} !~ /$type/ );
}
return 1;
},
# Check that OpenID macros exists
checkAttrAndMacros => sub {
my @tmp;
foreach my $k ( keys %$conf ) {
if ( $k =~
/^(?:openIdSreg_(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)|whatToTrace)$/
)
{
my $v = $conf->{$k};
$v =~ s/^$//;
next if ( $v =~ /^_/ );
push @tmp, $k
unless (
defined(
$conf->{exportedVars}->{$v}
or defined( $conf->{macros}->{$v} )
)
);
}
}
return (
1,
(
@tmp
? 'Values of parameter(s) "'
. join( ', ', @tmp )
. '" are not defined in exported attributes or macros'
: ''
)
);
},
# Test that variables are exported if Google is used as UserDB
checkUserDBGoogleAXParams => sub {
my @tmp;
if ( $conf->{userDB} =~ /^Google/ ) {
while ( my ( $k, $v ) = each %{ $conf->{exportedVars} } ) {
if ( $v !~ Lemonldap::NG::Common::Regexp::GOOGLEAXATTR() ) {
push @tmp, $v;
}
}
}
return (
1,
(
@tmp
? 'Values of parameter(s) "'
. join( ', ', @tmp )
. '" are not exported by Google'
: ''
)
);
},
# Test that variables are exported if OpenID is used as UserDB
checkUserDBOpenIDParams => sub {
my @tmp;
if ( $conf->{userDB} =~ /^OpenID/ ) {
while ( my ( $k, $v ) = each %{ $conf->{exportedVars} } ) {
if ( $v !~ Lemonldap::NG::Common::Regexp::OPENIDSREGATTR() )
{
push @tmp, $v;
}
}
}
return (
1,
(
@tmp
? 'Values of parameter(s) "'
. join( ', ', @tmp )
. '" are not exported by OpenID SREG'
: ''
)
);
},
# Try to use Apache::Session module
testApacheSession => sub {
my ( $id, %h );
return 1
if ( $Lemonldap::NG::Handler::CGI::globalStorage eq
$conf->{globalStorage}
or $conf->{globalStorage} eq
'Lemonldap::NG::Common::Apache::Session::SOAP' );
eval "use $conf->{globalStorage}";
return ( -1, "Unknown package $conf->{globalStorage}" ) if ($@);
eval {
tie %h, $conf->{globalStorage}, undef,
$conf->{globalStorageOptions};
};
return ( -1, "Unable to create a session ($@)" )
if ( $@ or not tied(%h) );
eval {
$h{a} = 1;
$id = $h{_session_id} or return ( -1, 'No _session_id' );
untie(%h);
tie %h, $conf->{globalStorage}, $id,
$conf->{globalStorageOptions};
};
return ( -1, "Unable to insert datas ($@)" ) if ($@);
return ( -1, "Unable to recover data stored" )
unless ( $h{a} == 1 );
eval { tied(%h)->delete; };
return ( -1, "Unable to delete session ($@)" ) if ($@);
my $gc = $Lemonldap::NG::Handler::CGI::globalStorage;
return ( -1,
'All sessions may be lost and you must restart all your Apache servers'
) if ( $conf->{globalStorage} ne $gc );
return 1;
},
# Warn if cookie name has changed
cookieNameChanged => sub {
return (
1,
(
$Lemonldap::NG::Handler::CGI::cookieName ne
$conf->{cookieName}
? 'Cookie name has changed, you must restart all your Apache servers'
: ()
)
);
},
# Warn if manager seems to be unprotected
managerProtection => sub {
return (
1,
(
$conf->{cfgAuthor} eq 'anonymous'
? 'Your manager seems to be unprotected'
: ''
)
);
},
# Test SMTP connection and authentication
smtpConnectionAuthentication => sub {
# Skip test if no SMTP configuration
return 1 unless ( $conf->{SMTPServer} );
# Use SMTP
eval "use Net::SMTP";
return ( 0, "Net::SMTP module is required to use SMTP server" )
if ($@);
# Create SMTP object
my $smtp = Net::SMTP->new( $conf->{SMTPServer} );
return ( 0,
"SMTP connection to " . $conf->{SMTPServer} . " failed" )
unless ($smtp);
# Skip other tests if no authentication
return 1
unless ( $conf->{SMTPAuthUser} and $conf->{SMTPAuthPass} );
# Try authentication
return ( 0, "SMTP authentication failed" )
unless $smtp->auth( $conf->{SMTPAuthUser},
$conf->{SMTPAuthPass} );
# Return
return 1;
},
# 2. MODIFICATIONS
# Remove unused and non-customized parameters
compactModules => sub {
foreach my $k ( keys %$conf ) {
# No analysis for hash keys
next if ( ref $conf->{$k} );
# Check federation modules
foreach my $type (qw(CAS OpenID SAML)) {
# Check authChoice values
my ( $authChoice, $userDBChoice ) = ( undef, undef );
if ( $conf->{authentication} eq 'Choice'
and defined $conf->{authChoiceModules} )
{
foreach ( keys %{ $conf->{authChoiceModules} } ) {
my ( $auth, $userDB, $passwordDB ) =
split( '|', $conf->{authChoiceModules}->{$_} );
$authChoice = 1 if $auth =~ /$type/i;
$userDBChoice = 1 if $userDB =~ /$type/i;
}
}
if (
(
$k =~ /^$type/i
and not( $conf->{"issuerDB${type}Activation"} )
and not( $conf->{authentication} =~ /$type/i )
and not( $conf->{userDB} =~ /$type/i )
and not( defined $authChoice
or defined $userDBChoice )
)
)
{
my $v = $self->defaultConf()->{$k};
if ( defined($v) and $conf->{$k} eq $v ) {
delete $conf->{$k};
}
}
}
return 1;
}
},
};
}
1;