From d18918b020e863dfe4b379ac23b9f03d4fe9c86c Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Sat, 26 Dec 2015 20:08:31 +0000 Subject: [PATCH] Move files that should be used only by jsongenerator.pl in Manager/Build --- Makefile | 4 +- lemonldap-ng-manager/MANIFEST | 5 +- lemonldap-ng-manager/TODO.md | 12 - .../lib/Lemonldap/NG/Manager.pm | 4 +- .../lib/Lemonldap/NG/Manager/Attributes.pm | 3544 ++++++++--------- .../Lemonldap/NG/Manager/Build/Attributes.pm | 2151 ++++++++++ .../NG/Manager/{ => Build}/CTrees.pm | 4 +- .../Lemonldap/NG/Manager/{ => Build}/Tree.pm | 4 +- lemonldap-ng-manager/scripts/jsongenerator.pl | 57 +- .../site/static/forms/README.md | 4 +- lemonldap-ng-manager/t/03-HTML-forms.t | 12 +- lemonldap-ng-manager/t/90-translations.t | 10 +- 12 files changed, 3792 insertions(+), 2019 deletions(-) create mode 100644 lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm rename lemonldap-ng-manager/lib/Lemonldap/NG/Manager/{ => Build}/CTrees.pm (98%) rename lemonldap-ng-manager/lib/Lemonldap/NG/Manager/{ => Build}/Tree.pm (99%) diff --git a/Makefile b/Makefile index 2d45173b6..33a99b01a 100644 --- a/Makefile +++ b/Makefile @@ -120,8 +120,8 @@ ERASECONFIG=1 # Set to 0 if you do not want to replace your configuration # GENERATED SRC FILESlemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm MANAGERJSONSRC=$(SRCMANAGERDIR)/scripts/jsongenerator.pl \ - $(SRCMANAGERDIR)/lib/Lemonldap/NG/Manager/Attributes.pm \ - $(SRCMANAGERDIR)/lib/Lemonldap/NG/Manager/Tree.pm + $(SRCMANAGERDIR)/lib/Lemonldap/NG/Manager/Build/Attributes.pm \ + $(SRCMANAGERDIR)/lib/Lemonldap/NG/Manager/Build/Tree.pm MANAGERJSONDST=$(SRCMANAGERDIR)/site/static/struct.json \ $(SRCMANAGERDIR)/site/static/js/conftree.js \ $(SRCMANAGERDIR)/lib/Lemonldap/NG/Manager/Constants.pm \ diff --git a/lemonldap-ng-manager/MANIFEST b/lemonldap-ng-manager/MANIFEST index 3b852741f..73b1756db 100644 --- a/lemonldap-ng-manager/MANIFEST +++ b/lemonldap-ng-manager/MANIFEST @@ -7,15 +7,16 @@ eg/manager-server.psgi KINEMATIC.md lib/Lemonldap/NG/Manager.pm lib/Lemonldap/NG/Manager/Attributes.pm +lib/Lemonldap/NG/Manager/Build/Attributes.pm +lib/Lemonldap/NG/Manager/Build/CTrees.pm +lib/Lemonldap/NG/Manager/Build/Tree.pm lib/Lemonldap/NG/Manager/Conf.pm lib/Lemonldap/NG/Manager/Conf/Tests.pm lib/Lemonldap/NG/Manager/ConfParser.pm lib/Lemonldap/NG/Manager/Constants.pm -lib/Lemonldap/NG/Manager/CTrees.pm lib/Lemonldap/NG/Manager/Lib.pm lib/Lemonldap/NG/Manager/Notifications.pm lib/Lemonldap/NG/Manager/Sessions.pm -lib/Lemonldap/NG/Manager/Tree.pm Makefile.PL MANIFEST This list of files META.yml diff --git a/lemonldap-ng-manager/TODO.md b/lemonldap-ng-manager/TODO.md index f72a7dda9..572346a89 100644 --- a/lemonldap-ng-manager/TODO.md +++ b/lemonldap-ng-manager/TODO.md @@ -2,11 +2,6 @@ * Check for eval with SAML * Icon picker for application logo -* Change documentation lang when changing language - -## Bugs - -* SAML IDP/SP exported attributes not working ## Configuration management @@ -15,10 +10,8 @@ ### Struct & datas -* Tests for new confs * default values: TODO, deliver a "0" conf when no conf is available * Forms: - * file: load from URL + download * Grant session rule * OpenID white/black list * POST replay fields @@ -31,11 +24,6 @@ ## Sessions explorer -## Optimization - -* Use JSON to store datas: - * sessions: new Apache::Session::Serialize::JSON module - ## Doc * Wiki doc diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager.pm index 0e52bfcf8..f713e4db2 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager.pm @@ -121,8 +121,8 @@ Lemonldap::NG Manager contains 4 parts: =head2 Generation of static files -The `scripts/jsongenerator.pl` file uses Lemonldap::NG::Manager::Attributes, -Lemonldap::NG::Manager::Tree and Lemonldap::NG::Manager::CTrees to generate +The `scripts/jsongenerator.pl` file uses Lemonldap::NG::Manager::Build::Attributes, +Lemonldap::NG::Manager::Build::Tree and Lemonldap::NG::Manager::Build::CTrees to generate =over diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm index bb96473c5..84493fd46 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm @@ -1,2151 +1,1747 @@ -# This file contains the description of all configuration parameters -# It may be included only by batch files, never in portal or handler chain -# for performances reasons - -# DON'T FORGET TO RUN jsongenerator.pl AFTER EACH CHANGE - +# This file is generated by ./scripts/jsongenerator.pl. Don't modify it by hand package Lemonldap::NG::Manager::Attributes; our $VERSION = '1.9.0'; -use strict; -use Regexp::Common qw/URI/; - -my $perlExpr = sub { - my $s = eval { $_[0] }; - return $@ ? ( 0, "__badExpression__: $@" ) : (1); -}; sub types { return { - - # Simple text types - text => { - test => qr/.*/, - msgFail => '__malformedValue__', + 'authParamsText' => { + 'test' => sub { "DUMMY" } }, - password => { - test => qr/.*/, - msgFail => '__malformedValue__', + 'blackWhiteList' => { + 'test' => sub { "DUMMY" } }, - longtext => { - test => sub { 1 } + 'bool' => { + 'msgFail' => '__notABoolean__', + 'test' => qr/^[01]$/ }, - url => { - form => 'text', - test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, - msgFail => '__badUrl__', + 'boolOrExpr' => { + 'msgFail' => '__notAValidPerlExpression__', + 'test' => sub { "DUMMY" } }, - PerlModule => { - form => 'text', - test => qr/^[a-zA-Z][a-zA-Z0-9]*(?:::[a-zA-Z][a-zA-Z0-9]*)*$/, - msgFail => '__badPerlPackageName__', + 'catAndAppList' => { + 'test' => sub { "DUMMY" } }, - hostname => { - form => 'text', - test => qr/^(?:$Regexp::Common::URI::RFC2396::host)?$/, - msgFail => '__badHostname__', + 'file' => { + 'test' => sub { "DUMMY" } }, - pcre => { - form => 'text', - test => sub { - eval { qr/$_[0]/ }; - return $@ ? ( 0, "__badRegexp__: $@" ) : (1); - }, + 'hostname' => { + 'form' => 'text', + 'msgFail' => '__badHostname__', + 'test' => +qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))?$/ }, - lmAttrOrMacro => { - form => 'text', - test => sub { 1 }, + 'int' => { + 'msgFail' => '__notAnInteger__', + 'test' => qr/^\-?\d+$/ }, - - # Other types - int => { - test => qr/^\-?\d+$/, - msgFail => '__notAnInteger__', + 'keyText' => { + 'keyTest' => qr/^[a-zA-Z0-9_]+$/, + 'msgFail' => '__badValue__', + 'test' => qr/^.*$/ }, - bool => { - test => qr/^[01]$/, - msgFail => '__notABoolean__', + 'lmAttrOrMacro' => { + 'form' => 'text', + 'test' => sub { "DUMMY" } }, - trool => { - test => qr/^(?:-1|0|1)$/, - msgFail => '__authorizedValues__: -1, 0, 1', + 'longtext' => { + 'test' => sub { "DUMMY" } }, - boolOrExpr => { - test => $perlExpr, - msgFail => '__notAValidPerlExpression__', + 'menuApp' => { + 'test' => sub { "DUMMY" } }, - - # Files type (long text) - file => { - test => sub { 1 } + 'menuCat' => { + 'test' => sub { "DUMMY" } }, - RSAPublicKey => { - test => -qr/^(?:\-+\s*BEGIN\s+PUBLIC\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+PUBLIC\s+KEY\s*\-+)?[\r\n]*$/s, - msgFail => '__badPemEncoding__', + 'oidcmetadatajson' => { + 'test' => sub { "DUMMY" } }, - RSAPrivateKey => { - test => -qr/^(?:\-+\s*BEGIN\s+RSA\s+PRIVATE\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+RSA\s+PRIVATE\s+KEY\s*\-+)?[\r\n]*$/s, - msgFail => '__badPemEncoding__', + 'oidcmetadatajwks' => { + 'test' => sub { "DUMMY" } }, - - authParamsText => { - test => sub { 1 } + 'oidcOPMetaDataNode' => { + 'test' => sub { "DUMMY" } }, - blackWhiteList => { - test => sub { 1 } + 'oidcRPMetaDataNode' => { + 'test' => sub { "DUMMY" } }, - catAndAppList => { - test => sub { 1 } + 'password' => { + 'msgFail' => '__malformedValue__', + 'test' => qr/.*/ }, - keyText => { - keyTest => qr/^[a-zA-Z0-9_]+$/, - test => qr/^.*$/, - msgFail => '__badValue__', + 'pcre' => { + 'form' => 'text', + 'test' => sub { "DUMMY" } }, - menuApp => { - test => sub { 1 } + 'PerlModule' => { + 'form' => 'text', + 'msgFail' => '__badPerlPackageName__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9]*(?:::[a-zA-Z][a-zA-Z0-9]*)*$/ }, - menuCat => { - test => sub { 1 } + 'portalskin' => { + 'test' => sub { "DUMMY" } }, - oidcOPMetaDataNode => { - test => sub { 1 } + 'portalskinbackground' => { + 'test' => sub { "DUMMY" } }, - oidcRPMetaDataNode => { - test => sub { 1 } + 'post' => { + 'test' => sub { "DUMMY" } }, - oidcmetadatajson => { - test => sub { 1 } + 'RSAPrivateKey' => { + 'msgFail' => '__badPemEncoding__', + 'test' => +qr/^(?:\-+\s*BEGIN\s+RSA\s+PRIVATE\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+RSA\s+PRIVATE\s+KEY\s*\-+)?[\r\n]*$/s }, - oidcmetadatajwks => { - test => sub { 1 } + 'RSAPublicKey' => { + 'msgFail' => '__badPemEncoding__', + 'test' => +qr/^(?:\-+\s*BEGIN\s+PUBLIC\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+PUBLIC\s+KEY\s*\-+)?[\r\n]*$/s }, - portalskin => { - test => sub { 1 } + 'rule' => { + 'test' => sub { "DUMMY" } }, - portalskinbackground => { - test => sub { 1 } + 'samlAssertion' => { + 'test' => sub { "DUMMY" } }, - post => { - test => sub { 1 } + 'samlAttribute' => { + 'test' => sub { "DUMMY" } }, - rule => { - test => sub { 1 } + 'samlIDPMetaDataNode' => { + 'test' => sub { "DUMMY" } }, - samlAssertion => { - test => sub { 1 } + 'samlService' => { + 'test' => sub { "DUMMY" } }, - samlAttribute => { - test => sub { 1 } + 'samlSPMetaDataNode' => { + 'test' => sub { "DUMMY" } }, - samlIDPMetaDataNode => { - test => sub { 1 } + 'select' => { + 'test' => sub { "DUMMY" } }, - samlSPMetaDataNode => { - test => sub { 1 } + 'text' => { + 'msgFail' => '__malformedValue__', + 'test' => qr/.*/ }, - samlService => { - test => sub { 1 } + 'trool' => { + 'msgFail' => '__authorizedValues__: -1, 0, 1', + 'test' => qr/^(?:-1|0|1)$/ }, - select => { - test => sub { - my $test = - grep { $_ eq $_[0] } map { $_->{k} } @{ $_[2]->{select} }; - return $test ? 1 : 0; - }, + 'url' => { + 'form' => 'text', + 'msgFail' => '__badUrl__', + 'test' => +qr/^(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)$/ }, - virtualHost => { - test => sub { 1 } - }, - + 'virtualHost' => { + 'test' => sub { "DUMMY" } + } }; } sub attributes { return { - - # Other - cfgNum => { - type => 'int', - default => 0, - documentation => 'Enable Cross Domain Authentication', + 'activeTimer' => { + 'default' => 1, + 'type' => 'bool' }, - cfgAuthor => { - type => 'text', - documentation => 'Name of the author of the current configuration', + 'ADPwdExpireWarning' => { + 'default' => 0, + 'type' => 'int' }, - cfgAuthorIP => { - type => 'text', - documentation => 'Uploader IP address of the current configuration', + 'ADPwdMaxAge' => { + 'default' => 0, + 'type' => 'int' }, - cfgDate => { - type => 'int', - documentation => 'Timestamp of the current configuration', + 'apacheAuthnLevel' => { + 'default' => 4, + 'type' => 'int' }, - cfgLog => { - type => 'longtext', - documentation => 'Configuration update log', - }, - confirmFormMethod => { - type => "select", - select => - [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ], - default => 'post', - documentation => 'HTTP method for confirm page form', - }, - customFunctions => { type => 'text', }, - https => { - default => 0, - type => 'bool', - documentation => 'Use HTTPS for redirection from portal', - }, - infoFormMethod => { - type => "select", - select => - [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ], - default => 'get', - documentation => 'HTTP method for info page form', - }, - port => { type => 'int', }, - jsRedirect => { - type => 'boolOrExpr', - default => 0, - documentation => 'Use javascript for redirections', - }, - logoutServices => { - type => 'keyTextContainer', - help => 'logoutforward.html', - default => {}, - documentation => 'Send logout trough GET request to these services', - }, - maintenance => { - default => 0, - type => 'bool', - documentation => 'Maintenance mode for all virtual hosts', - }, - portal => { - type => 'url', - default => 'http://auth.example.com/', - documentation => 'Portal URL', - }, - portalUserAttr => { - type => 'text', - default => '_user', - documentation => - 'Session parameter to display connected user in portal', - }, - redirectFormMethod => { - type => "select", - select => - [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ], - default => 'get', - documentation => 'HTTP method for redirect page form', - }, - reloadUrls => { - type => 'keyTextContainer', - help => 'configlocation.html#configuration_reload', - keyTest => qr/^$Regexp::Common::URI::RFC2396::host$/, - test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, - msgFail => '__badUrl__' - }, - staticPrefix => { - type => 'text', - documentation => 'Prefix of static files for HTML templates', - }, - syslog => { - type => 'text', - test => qr/^(?:auth|authpriv|daemon|local\d|user)?$/, - msgFail => - '__authorizedValues__: auth, authpriv, daemon, local0-7, user', - default => '', - documentation => 'Syslog facility', - }, - - # Manager - protection => { - type => 'text', - test => qr/^(?:none|authenticate|manager|)$/, - msgFail => '__authorizedValues__: none authenticate manager', - default => 'none', - documentation => 'Manager protection method', - }, - - # Menu - activeTimer => { - default => 0, - type => 'bool', - default => 1, - documentation => 'Enable timers on portal pages', - }, - applicationList => { - type => 'catAndAppList', - help => 'portalmenu.html#categories_and_applications', - default => { - default => { catname => 'Default category', type => "category" } + 'applicationList' => { + 'default' => { + 'default' => { + 'catname' => 'Default category', + 'type' => 'category' + } }, - documentation => 'Applications list', + 'type' => 'catAndAppList' }, - portalOpenLinkInNewWindow => { - type => 'bool', - default => 0, - documentation => 'Open applications in new windows', + 'authChoiceModules' => { + 'keyTest' => qr/^(\d*)?[a-zA-Z0-9_]+$/, + 'type' => 'authChoiceContainer' }, - portalPingInterval => { - type => 'int', - default => 60000, - documentation => 'Interval in ms between portal Ajax pings ', + 'authChoiceParam' => { + 'default' => 'lmAuth', + 'type' => 'text' }, - portalSkin => { - type => 'portalskin', - default => 'bootstrap', - documentation => 'Name of portal skin', - select => [ - { k => 'bootstrap', v => 'Bootstrap' }, - { k => 'pastel', v => 'Pastel' }, - { k => 'impact', v => 'Impact' }, - { k => 'dark', v => 'Dark' }, - ], + 'authentication' => { + 'default' => 'Demo', + 'type' => 'select' }, - portalSkinBackground => { - type => 'portalskinbackground', - documentation => 'Background image of portal skin', - select => [ - { k => "", v => 'None' }, - { - k => "1280px-Anse_Source_d'Argent_2-La_Digue.jpg", - v => 'Anse' - }, - { - k => -"1280px-Autumn-clear-water-waterfall-landscape_-_Virginia_-_ForestWander.jpg", - v => 'Waterfall' - }, - { k => "1280px-BrockenSnowedTrees.jpg", v => 'Snowed Trees' }, - { - k => "1280px-Cedar_Breaks_National_Monument_partially.jpg", - v => 'National Monument' - }, - { - k => "1280px-Parry_Peak_from_Winter_Park.jpg", - v => 'Winter' - }, - { k => "Aletschgletscher_mit_Pinus_cembra1.jpg", v => 'Pinus' }, - ], + 'AuthLDAPFilter' => { + 'type' => 'text' }, - portalSkinRules => { - type => 'keyTextContainer', - help => 'portalcustom.html', - keyTest => $perlExpr, - keyMsgFail => 'Bad skin rule', - test => qr/^\w+$/, - msgFail => '__badValue__', + 'browserIdAuthnLevel' => { + 'default' => 1, + 'type' => 'int' }, - - # Security - cda => { - default => 0, - type => 'bool', - documentation => 'Enable Cross Domain Authentication', + 'browserIdAutoLogin' => { + 'type' => 'bool' }, - checkXSS => { - default => 1, - type => 'bool', - documentation => 'Check XSS', + 'browserIdBackgroundColor' => { + 'type' => 'text' }, - grantSessionRules => { - type => 'keyTextContainer', - keyTest => $perlExpr, + 'browserIdSiteLogo' => { + 'type' => 'text' }, - hiddenAttributes => { - type => 'text', - default => '_password', - documentation => 'Name of attributes to hide in logs', + 'browserIdSiteName' => { + 'type' => 'text' }, - key => { - type => 'password', - documentation => 'Secret key', + 'browserIdVerificationURL' => { + 'type' => 'text' }, - portalAntiFrame => { - default => 1, - type => 'bool', - documentation => 'Avoid portal to be displayed inside frames', + 'captcha_login_enabled' => { + 'default' => 0, + 'type' => 'bool' }, - portalCheckLogins => { - default => 1, - type => 'bool', - default => 1, - documentation => 'Display login history checkbox in portal', + 'captcha_mail_enabled' => { + 'default' => 0, + 'type' => 'bool' }, - portalForceAuthn => { - default => 0, - type => 'bool', - documentation => 'Force to authenticate when displaying portal', + 'captcha_register_enabled' => { + 'default' => 1, + 'type' => 'bool' }, - portalForceAuthnInterval => { - type => 'int', - default => 0, - documentation => -'Minimum number of seconds since last authentifcation to force reauthentication', + 'captcha_size' => { + 'default' => 6, + 'type' => 'int' }, - randomPasswordRegexp => { - type => 'pcre', - default => '[A-Z]{3}[a-z]{5}.\d{2}', - documentation => 'Regular expression to create a random password', + 'captchaStorage' => { + 'default' => 'Apache::Session::File', + 'type' => 'text' }, - trustedDomains => { type => 'text', }, - storePassword => { - default => 0, - type => 'bool', - documentation => 'Store password in session', + 'captchaStorageOptions' => { + 'default' => { + 'Directory' => '/var/lib/lemonldap-ng/captcha/' + }, + 'type' => 'keyTextContainer' }, - timeout => { - type => 'int', - default => 72000, - documentation => 'Session timeout on server side', + 'CAS_authnLevel' => { + 'default' => 1, + 'type' => 'int' }, - timeoutActivity => { - select => [ - { k => '0', v => 'None' }, - { k => '900', v => '15 min' }, - { k => '1800', v => '30 min' }, - { k => '2700', v => '45 min' }, - { k => '3600', v => '60 min' }, - ], - type => 'select', - default => 0, - documentation => 'Session activity timeout on server side', + 'CAS_CAFile' => { + 'type' => 'text' }, - trustedProxies => { - type => 'text', - default => '', - documentation => 'Trusted proxies', + 'CAS_gateway' => { + 'type' => 'bool' }, - userControl => { - type => 'pcre', - default => '^[\w\.\-@]+$', - documentation => 'Regular expression to validate login', + 'CAS_pgtFile' => { + 'default' => '/tmp/pgt.txt', + 'type' => 'text' }, - useRedirectOnError => { - type => 'bool', - default => 1, - documentation => 'Use 302 redirect code for error (500)', + 'CAS_proxiedServices' => { + 'keyTest' => qr/^\w+$/, + 'type' => 'keyTextContainer' }, - useRedirectOnForbidden => { - default => 0, - type => 'bool', - documentation => 'Use 302 redirect code for forbidden (403)', + 'CAS_renew' => { + 'type' => 'bool' }, - useSafeJail => { - default => 1, - type => 'bool', - documentation => 'Activate Safe jail', + 'CAS_url' => { + 'msgFail' => '__badUrl__', + 'test' => +qr/^(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)$/, + 'type' => 'text' }, - whatToTrace => { - type => 'lmAttrOrMacro', - default => 'uid', - documentation => 'Session parameter used to fill REMOTE_USER', + 'casAccessControlPolicy' => { + 'default' => 'none', + 'type' => 'select' }, - - # History - failedLoginNumber => { - default => 5, - type => 'int', - documentation => 'Number of failures stored in login history', + 'casAttr' => { + 'type' => 'text' }, - loginHistoryEnabled => { - default => 0, - type => 'bool', - default => 1, - documentation => 'Enable login history', + 'casAttributes' => { + 'type' => 'keyTextContainer' }, - portalDisplayLoginHistory => { - type => 'boolOrExpr', - default => 1, - documentation => 'Display login history tab in portal', + 'casStorage' => { + 'type' => 'text' }, - successLoginNumber => { - default => 5, - type => 'int', - documentation => 'Number of success stored in login history', + 'casStorageOptions' => { + 'type' => 'keyTextContainer' }, - - # Other displays - portalDisplayAppslist => { - type => 'boolOrExpr', - default => 1, - documentation => 'Display applications tab in portal', + 'cda' => { + 'default' => 0, + 'type' => 'bool' }, - portalDisplayChangePassword => { - type => 'boolOrExpr', - default => '$_auth =~ /^(LDAP|DBI|Demo)$/', - documentation => 'Display password tab in portal', + 'cfgAuthor' => { + 'type' => 'text' }, - portalDisplayLogout => { - default => 1, - type => 'boolOrExpr', - documentation => 'Display logout tab in portal', + 'cfgAuthorIP' => { + 'type' => 'text' }, - portalDisplayRegister => { - default => 1, - type => 'bool', - documentation => 'Display register button in portal', + 'cfgDate' => { + 'type' => 'int' }, - portalDisplayResetPassword => { - default => 1, - type => 'bool', - documentation => 'Display reset password button in portal', + 'cfgLog' => { + 'type' => 'longtext' }, - - # Cookies - cookieExpiration => { type => 'text', }, - cookieName => { - type => 'text', - test => qr/^[a-zA-Z][a-zA-Z0-9_-]*$/, - msgFail => '__badCookieName__', - default => 'lemonldap', - documentation => 'Name of the main cookie', + 'cfgNum' => { + 'default' => 0, + 'type' => 'int' }, - domain => { - type => 'text', - test => qr/^(?:$Regexp::Common::URI::RFC2396::hostname)?/, - msgFail => '__badDomainName__', - default => 'example.com', - documentation => 'DNS domain', + 'checkXSS' => { + 'default' => 1, + 'type' => 'bool' }, - httpOnly => { - default => 1, - type => 'bool', - documentation => 'Enable httpOnly flag in cookie', + 'confirmFormMethod' => { + 'default' => 'post', + 'type' => 'select' }, - securedCookie => { - type => 'select', - select => [ - { k => '0', v => 'unsecuredCookie' }, - { k => '1', v => 'securedCookie' }, - { k => '2', v => 'doubleCookie' }, - { k => '3', v => 'doubleCookieForSingleSession' }, - ], - default => 0, - documentation => 'Cookie securisation method', + 'cookieExpiration' => { + 'type' => 'text' }, - - # Notification - notificationStorage => { type => 'PerlModule', }, - notificationWildcard => { - type => 'text', - default => 'allusers', - documentation => 'Notification string to match all users', + 'cookieName' => { + 'default' => 'lemonldap', + 'msgFail' => '__badCookieName__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_-]*$/, + 'type' => 'text' }, - notificationXSLTfile => { type => 'text', }, - notification => { - default => 0, - type => 'bool', - documentation => 'Notification activation', + 'customFunctions' => { + 'type' => 'text' }, - notificationStorage => { - type => 'PerlModule', - default => 'File', - documentation => 'Notification backend', + 'dbiAuthChain' => { + 'type' => 'text' }, - notificationStorageOptions => { - type => 'keyTextContainer', - default => { dirName => '/var/lib/lemonldap-ng/notifications', }, - documentation => 'Notification backend options', + 'dbiAuthLoginCol' => { + 'type' => 'text' }, - - # Captcha - captcha_login_enabled => { - default => 0, - type => 'bool', - documentation => 'Captcha on login page', + 'dbiAuthnLevel' => { + 'default' => 2, + 'type' => 'int' }, - captcha_mail_enabled => { - default => 0, - type => 'bool', - documentation => 'Captcha on password reset page', + 'dbiAuthPassword' => { + 'type' => 'password' }, - captcha_register_enabled => { - default => 1, - type => 'bool', - documentation => 'Captcha on account creation page', + 'dbiAuthPasswordCol' => { + 'type' => 'text' }, - captcha_size => { - type => 'int', - default => 6, - documentation => 'Captcha size', + 'dbiAuthPasswordHash' => { + 'type' => 'text' }, - - #captcha_data => { - #captcha_output => { - captchaStorage => { - type => 'PerlModule', - default => 'Apache::Session::File', - documentation => 'Captcha backend module', + 'dbiAuthTable' => { + 'type' => 'text' }, - captchaStorageOptions => { - type => 'keyTextContainer', - default => { 'Directory' => '/var/lib/lemonldap-ng/captcha/', }, - documentation => 'Captcha backend module options', + 'dbiAuthUser' => { + 'type' => 'text' }, - - # Variables - exportedVars => { - type => 'keyTextContainer', - help => 'exportedvars.html', - keyTest => qr/^!?[_a-zA-Z][a-zA-Z0-9_]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[_a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => { 'UA' => 'HTTP_USER_AGENT' }, - documentation => 'Main exported variables', + 'dbiExportedVars' => { + 'default' => {}, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' }, - groups => { - type => 'keyTextContainer', - help => - 'exportedvars.html#extend_variables_using_macros_and_groups', - test => $perlExpr, - default => {}, - documentation => 'Groups', + 'dbiPasswordMailCol' => { + 'type' => 'text' }, - macros => { - type => 'keyTextContainer', - help => - 'exportedvars.html#extend_variables_using_macros_and_groups', - keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/, - keyMsgFail => 'Bad macro name', - test => $perlExpr, - default => {}, - documentation => 'Macros', + 'dbiUserChain' => { + 'type' => 'text' }, - - # Storage - globalStorage => { - type => 'PerlModule', - default => 'Apache::Session::File', - documentation => 'Session backend module', + 'dbiUserPassword' => { + 'type' => 'password' }, - globalStorageOptions => { - type => 'keyTextContainer', - default => { - 'Directory' => '/var/lib/lemonldap-ng/sessions/', - 'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/', + 'dbiUserTable' => { + 'type' => 'text' + }, + 'dbiUserUser' => { + 'type' => 'text' + }, + 'demoExportedVars' => { + 'default' => { + 'cn' => 'cn', + 'mail' => 'mail', + 'uid' => 'uid' + }, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'domain' => { + 'default' => 'example.com', + 'msgFail' => '__badDomainName__', + 'test' => +qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?/, + 'type' => 'text' + }, + 'exportedAttr' => { + 'type' => 'text' + }, + 'exportedHeaders' => { + 'keyTest' => +'(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)', + 'type' => 'keyTextContainer' + }, + 'exportedVars' => { + 'default' => { + 'UA' => 'HTTP_USER_AGENT' + }, + 'keyTest' => qr/^!?[_a-zA-Z][a-zA-Z0-9_]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[_a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'facebookAppId' => { + 'type' => 'text' + }, + 'facebookAppSecret' => { + 'type' => 'text' + }, + 'facebookAuthnLevel' => { + 'default' => 1, + 'type' => 'int' + }, + 'facebookExportedVars' => { + 'default' => {}, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'failedLoginNumber' => { + 'default' => 5, + 'type' => 'int' + }, + 'globalStorage' => { + 'default' => 'Apache::Session::File', + 'type' => 'text' + }, + 'globalStorageOptions' => { + 'default' => { + 'Directory' => '/var/lib/lemonldap-ng/sessions/', 'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', + 'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/' }, - documentation => 'Session backend module options', + 'type' => 'keyTextContainer' }, - localSessionStorage => { - type => 'PerlModule', - default => 'Cache::FileCache', - , documentation => 'Sessions cache module', + 'googleAuthnLevel' => { + 'default' => 1, + 'type' => 'int' }, - localSessionStorageOptions => { - type => 'keyTextContainer', - default => { - 'namespace' => 'lemonldap-ng-sessions', + 'googleExportedVars' => { + 'default' => {}, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'grantSessionRules' => { + 'keyTest' => sub { "DUMMY" }, + 'type' => 'keyTextContainer' + }, + 'groups' => { + 'default' => {}, + 'test' => $VAR1->{'grantSessionRules'}{'keyTest'}, + 'type' => 'keyTextContainer' + }, + 'hiddenAttributes' => { + 'default' => '_password', + 'type' => 'text' + }, + 'hideOldPassword' => { + 'default' => 0, + 'type' => 'bool' + }, + 'httpOnly' => { + 'default' => 1, + 'type' => 'bool' + }, + 'https' => { + 'default' => 0, + 'type' => 'bool' + }, + 'infoFormMethod' => { + 'default' => 'get', + 'type' => 'select' + }, + 'issuerDBCASActivation' => { + 'default' => 0, + 'type' => 'bool' + }, + 'issuerDBCASPath' => { + 'default' => '^/cas/', + 'type' => 'text' + }, + 'issuerDBCASRule' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'issuerDBOpenIDActivation' => { + 'default' => 0, + 'type' => 'bool' + }, + 'issuerDBOpenIDConnectActivation' => { + 'default' => '0', + 'type' => 'bool' + }, + 'issuerDBOpenIDConnectPath' => { + 'default' => '^/oauth2/', + 'type' => 'text' + }, + 'issuerDBOpenIDConnectRule' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'issuerDBOpenIDPath' => { + 'default' => '^/openidserver/', + 'type' => 'text' + }, + 'issuerDBOpenIDRule' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'issuerDBSAMLActivation' => { + 'default' => 0, + 'type' => 'bool' + }, + 'issuerDBSAMLPath' => { + 'default' => '^/saml/', + 'type' => 'text' + }, + 'issuerDBSAMLRule' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'jsRedirect' => { + 'default' => 0, + 'type' => 'boolOrExpr' + }, + 'key' => { + 'type' => 'password' + }, + 'ldapAuthnLevel' => { + 'default' => 2, + 'type' => 'int' + }, + 'ldapBase' => { + 'default' => 'dc=example,dc=com', + 'msgFail' => '__badValue__', + 'test' => qr/^(?:\w+=.*|)$/, + 'type' => 'text' + }, + 'ldapChangePasswordAsUser' => { + 'default' => 0, + 'type' => 'bool' + }, + 'ldapExportedVars' => { + 'default' => { + 'cn' => 'cn', + 'mail' => 'mail', + 'uid' => 'uid' + }, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'LDAPFilter' => { + 'type' => 'text' + }, + 'ldapGroupAttributeName' => { + 'default' => 'member', + 'type' => 'text' + }, + 'ldapGroupAttributeNameGroup' => { + 'default' => 'dn', + 'type' => 'text' + }, + 'ldapGroupAttributeNameSearch' => { + 'default' => 'cn', + 'type' => 'text' + }, + 'ldapGroupAttributeNameUser' => { + 'default' => 'dn', + 'type' => 'text' + }, + 'ldapGroupBase' => { + 'type' => 'text' + }, + 'ldapGroupObjectClass' => { + 'default' => 'groupOfNames', + 'type' => 'text' + }, + 'ldapGroupRecursive' => { + 'default' => 0, + 'type' => 'bool' + }, + 'ldapPasswordResetAttribute' => { + 'default' => 'pwdReset', + 'type' => 'text' + }, + 'ldapPasswordResetAttributeValue' => { + 'default' => 'TRUE', + 'type' => 'text' + }, + 'ldapPort' => { + 'default' => 389, + 'type' => 'int' + }, + 'ldapPpolicyControl' => { + 'default' => 0, + 'type' => 'bool' + }, + 'ldapPwdEnc' => { + 'default' => 'utf-8', + 'msgFail' => '__badEncoding__', + 'test' => qr/^[a-zA-Z0-9_][a-zA-Z0-9_\-]*[a-zA-Z0-9_]$/, + 'type' => 'text' + }, + 'ldapRaw' => { + 'type' => 'text' + }, + 'ldapServer' => { + 'default' => 'ldap://localhost', + 'test' => sub { "DUMMY" }, + 'type' => 'text' + }, + 'ldapSetPassword' => { + 'default' => 0, + 'type' => 'bool' + }, + 'ldapTimeout' => { + 'default' => 120, + 'type' => 'int' + }, + 'ldapUsePasswordResetAttribute' => { + 'default' => 1, + 'type' => 'bool' + }, + 'ldapVersion' => { + 'default' => 3, + 'type' => 'int' + }, + 'localSessionStorage' => { + 'default' => 'Cache::FileCache', + 'type' => 'text' + }, + 'localSessionStorageOptions' => { + 'default' => { + 'cache_depth' => 3, + 'cache_root' => '/tmp', 'default_expires_in' => 600, 'directory_umask' => '007', - 'cache_root' => '/tmp', - 'cache_depth' => 3, + 'namespace' => 'lemonldap-ng-sessions' }, - documentation => 'Sessions cache module options', + 'type' => 'keyTextContainer' }, - - # Persistent storage - persistentStorage => { type => 'PerlModule', }, - persistentStorageOptions => { type => 'keyTextContainer', }, - sessionDataToRemember => { - type => 'keyTextContainer', - keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/, - keyMsgFail => 'Invalid session data', - }, - - # SAML issuer - issuerDBSAMLActivation => { - default => 0, - type => 'bool', - documentation => 'SAML IDP activation', - }, - issuerDBSAMLPath => { - type => 'pcre', - default => '^/saml/', - documentation => 'SAML IDP request path', - }, - issuerDBSAMLRule => { - type => 'boolOrExpr', - default => 1, - documentation => 'SAML IDP rule', - }, - - # OpenID-Connect issuer - issuerDBOpenIDConnectActivation => { - type => 'bool', - default => '0', - documentation => 'OpenID Connect server activation', - }, - issuerDBOpenIDConnectPath => { - type => 'text', - default => '^/oauth2/', - documentation => 'OpenID Connect server request path', - }, - issuerDBOpenIDConnectRule => { - type => 'boolOrExpr', - default => 1, - documentation => 'OpenID Connect server rule', - }, - - # Password - mailOnPasswordChange => { - default => 0, - type => 'bool', - documentation => 'Send a mail when password is changed', - }, - portalRequireOldPassword => { - default => 1, - type => 'bool', - documentation => 'Old password is required to change the password', - }, - hideOldPassword => { - default => 0, - type => 'bool', - documentation => 'Hide old password in portal', - }, - - # Mails - mailBody => { type => 'longtext', }, - mailCharset => { - type => 'text', - default => 'utf-8', - documentation => 'Mail charset', - }, - mailConfirmBody => { type => 'longtext', }, - mailConfirmSubject => { - type => 'text', - default => '[LemonLDAP::NG] Password reset confirmation', - documentation => 'Mail subject for reset confirmation', - }, - mailFrom => { - type => 'text', - default => 'noreply@example.com', - documentation => 'Sender email', - }, - mailReplyTo => { type => 'text', }, - mailSessionKey => { - type => 'text', - default => 'mail', - documentation => 'Session parameter where mail is stored', - }, - mailSubject => { - type => 'text', - default => '[LemonLDAP::NG] Your new password', - documentation => 'Mail subject for new password email', - }, - mailTimeout => { - type => 'int', - default => 0, - documentation => 'Mail session timeout', - }, - mailUrl => { - type => 'url', - default => 'http://auth.example.com/mail.pl', - documentation => 'URL of password reset page', - }, - SMTPServer => { - type => 'hostname', - default => '', - documentation => 'SMTP Server', - }, - SMTPAuthUser => { type => 'text', }, - SMTPAuthPass => { type => 'password', }, - - # Registration - registerConfirmSubject => { - type => 'text', - default => '[LemonLDAP::NG] Account register confirmation', - documentation => 'Mail subject for register confirmation', - }, - registerDB => { - type => 'select', - select => [ - { k => 'AD', v => 'Active Directory' }, - { k => 'Demo', v => 'Demonstration' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Null', v => 'None' }, - ], - default => 'Demo', - documentation => 'Register module', - }, - registerDoneSubject => { - type => 'text', - default => '[LemonLDAP::NG] Your new account', - documentation => 'Mail subject when register is done', - }, - registerTimeout => { - default => 0, - type => 'int', - documentation => 'Register session timeout', - }, - registerUrl => { - type => 'text', - default => 'http://auth.example.com/register.pl', - documentation => 'URL of register page', - }, - - # Single session - notifyDeleted => { - default => 1, - type => 'bool', - documentation => 'Show deleted sessions in portal', - }, - notifyOther => { - default => 0, - type => 'bool', - documentation => 'Show other sessions in portal', - }, - singleSession => { - default => 0, - type => 'bool', - documentation => 'Allow only one session per user', - }, - singleIP => { - default => 0, - type => 'bool', - documentation => 'Allow only one session per IP', - }, - singleUserByIP => { - default => 0, - type => 'bool', - }, - singleSessionUserByIP => { - default => 0, - type => 'bool', - documentation => 'Allow only one session per user on an IP', - }, - - # SOAP server - Soap => { - default => 0, - type => 'bool', - documentation => 'Enable SOAP services', - }, - exportedAttr => { type => 'text', }, - - ## Virtualhosts - - # Fake attribute: used by manager REST API to agglomerate all other - # nodes - virtualHosts => { - type => 'virtualHostContainer', - help => 'configvhost.html', - template => 'virtualHost', - }, - - locationRules => { - type => 'ruleContainer', - help => 'writingrulesand_headers.html#rules', - keyTest => $Regexp::Common::URI::RFC2396::hostname, - msgFail => '__badHostname__', - default => { - default => 'deny', + 'locationRules' => { + 'default' => { + 'default' => 'deny' }, - documentation => 'Virtualhost rules', - }, - exportedHeaders => { - type => 'keyTextContainer', - help => 'writingrulesand_headers.html#headers', - keyTest => $Regexp::Common::URI::RFC2396::hostname, - keyMsgFail => '__badHostname__', - documentation => 'Virtualhost headers', - }, - post => { - type => 'postContainer', - help => 'formreplay.html', - keyTest => $Regexp::Common::URI::RFC2396::hostname, - keyMsgFail => '__badHostname__', - documentation => 'Virtualhost urls/Datas to post', - }, - - vhostOptions => { - type => 'subContainer', - }, - vhostPort => { - type => 'int', - default => -1, - }, - vhostHttps => { - type => 'trool', - default => -1, - }, - vhostMaintenance => { - type => 'bool', - default => 0, - }, - vhostAliases => { - type => 'text', - }, - - # CAS IDP - casAttr => { type => 'text', }, - casAttributes => { type => 'keyTextContainer', }, - casAccessControlPolicy => { - type => 'select', - select => [ - { k => 'none', v => 'None' }, - { k => 'error', v => 'Display error on portal' }, - { k => 'faketicket', v => 'Send a fake service ticket' }, - ], - default => 'none', - documentation => 'CAS access control policy', - }, - casStorage => { type => 'PerlModule', }, - casStorageOptions => { - type => 'keyTextContainer', - }, - issuerDBCASActivation => { - default => 0, - type => 'bool', - documentation => 'CAS server activation', - }, - issuerDBCASPath => { - type => 'pcre', - default => '^/cas/', - documentation => 'CAS server request path', - }, - issuerDBCASRule => { - type => 'boolOrExpr', - default => 1, - documentation => 'CAS server rule', - }, - - # OpenID Issuer - issuerDBOpenIDActivation => { - default => 0, - type => 'bool', - documentation => 'OpenID server activation', - }, - issuerDBOpenIDPath => { - type => 'pcre', - default => '^/openidserver/', - documentation => 'OpenID server request path', - }, - issuerDBOpenIDRule => { - type => 'boolOrExpr', - default => 1, - documentation => 'OpenID server rule', - }, - - openIdIssuerSecret => { type => 'text', }, - openIdAttr => { type => 'text', }, - openIdSreg_fullname => { - type => 'lmAttrOrMacro', - default => 'cn', - documentation => 'OpenID SREG fullname session parameter', - }, - openIdSreg_nickname => { - type => 'lmAttrOrMacro', - default => 'uid', - documentation => 'OpenID SREG nickname session parameter', - }, - openIdSreg_language => { type => 'lmAttrOrMacro', }, - openIdSreg_postcode => { type => 'lmAttrOrMacro', }, - openIdSreg_timezone => { - type => 'lmAttrOrMacro', - default => '_timezone', - documentation => 'OpenID SREG timezone session parameter', - }, - openIdSreg_country => { type => 'lmAttrOrMacro', }, - openIdSreg_gender => { type => 'lmAttrOrMacro', }, - openIdSreg_email => { - type => 'lmAttrOrMacro', - default => 'mail', - documentation => 'OpenID SREG email session parameter', - }, - openIdSreg_dob => { type => 'lmAttrOrMacro', }, - openIdSPList => { type => 'blackWhiteList', default => '0;' }, - - # Zimbra - zimbraPreAuthKey => { type => 'text', }, - zimbraAccountKey => { type => 'text', }, - zimbraBy => { - type => 'select', - select => [ - { k => '', v => '' }, - { k => 'name', v => 'User name' }, - { k => 'id', v => 'User id' }, - { k => 'foreignPrincipal', v => 'Foreign principal' }, - ], - default => '', - }, - zimbraUrl => { type => 'url', }, - zimbraSsoUrl => { type => 'url', }, - - # Sympa - sympaSecret => { type => 'text', }, - sympaMailKey => { type => 'text', }, - - # Secure Token - secureTokenMemcachedServers => { - type => 'text', - default => '127.0.0.1:11211', - documentation => 'Secure Token Handler memcached servers', - }, - secureTokenExpiration => { - type => 'int', - default => 60, - documentation => 'Secure Token Handler token expiration', - }, - secureTokenAttribute => { - type => 'text', - default => 'uid', - documentation => 'Secure Token Handler attribute to store', - }, - secureTokenUrls => { - type => 'pcre', - default => '.*', - documentation => - 'Secure Token Handler regular expression to match protected URL', - }, - secureTokenHeader => { - type => 'text', - default => 'Auth-Token', - documentation => 'Secure Token Handler header name', - }, - secureTokenAllowOnError => { - default => 1, - type => 'bool', - documentation => 'Secure Token Handler allow request on error', - }, - ######### - ## SAML # - ######### - samlEntityID => { - type => 'text', - default => '#PORTAL#/saml/metadata', - documentation => 'SAML service entityID', - }, - samlOrganizationDisplayName => { - type => 'text', - default => 'Example', - documentation => 'SAML service organization display name', - }, - samlOrganizationName => { - type => 'text', - default => 'Example', - documentation => 'SAML service organization name', - }, - samlOrganizationURL => { - type => 'text', - default => 'http://www.example.com', - documentation => 'SAML service organization URL', - }, - samlNameIDFormatMapEmail => { - type => 'text', - default => 'mail', - documentation => 'SAML session parameter for NameID email', - }, - samlNameIDFormatMapX509 => { - type => 'text', - default => 'mail', - documentation => 'SAML session parameter for NameID x509', - }, - samlNameIDFormatMapWindows => { - type => 'text', - default => 'uid', - documentation => 'SAML session parameter for NameID windows', - }, - samlNameIDFormatMapKerberos => { - type => 'text', - default => 'uid', - documentation => 'SAML session parameter for NameID kerberos', - }, - samlAttributeAuthorityDescriptorAttributeServiceSOAP => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' - . '#PORTAL#/saml/AA/SOAP;', - documentation => 'SAML Attribute Authority SOAP', - }, - samlServicePrivateKeySig => { - type => 'RSAPrivateKey', - default => '', - documentation => 'SAML signature private key', - }, - samlServicePrivateKeySigPwd => { - type => 'password', - default => '', - documentation => 'SAML signature private key password', - }, - samlServicePublicKeySig => { - type => 'RSAPublicKey', - default => '', - documentation => 'SAML signature public key', - }, - samlServicePrivateKeyEnc => { - type => 'RSAPrivateKey', - default => '', - documentation => 'SAML encryption private key', - }, - samlServicePrivateKeyEncPwd => { type => 'password', }, - samlServicePublicKeyEnc => { - type => 'RSAPublicKey', - default => '', - documentation => 'SAML encryption public key', - }, - samlIdPResolveCookie => { - type => 'text', - default => 'lemonldapidp', - documentation => 'SAML IDP resolution cookie', - }, - samlMetadataForceUTF8 => { - default => 1, - type => 'bool', - documentation => 'SAML force metadata UTF8 conversion', - }, - samlStorage => { type => 'PerlModule', }, - samlStorageOptions => { type => 'keyTextContainer', }, - samlAuthnContextMapPassword => { - type => 'int', - default => 2, - documentation => 'SAML authn context password level', - }, - samlAuthnContextMapPasswordProtectedTransport => { - type => 'int', - default => 3, - documentation => - 'SAML authn context password protected transport level', - }, - samlAuthnContextMapTLSClient => { - type => 'int', - default => 5, - documentation => 'SAML authn context TLS client level', - }, - samlAuthnContextMapKerberos => { - type => 'int', - default => 4, - documentation => 'SAML authn context kerberos level', - }, - samlCommonDomainCookieActivation => { - default => 0, - type => 'bool', - documentation => 'SAML CDC activation', - }, - samlCommonDomainCookieDomain => { - type => 'text', - test => qr/^$Regexp::Common::URI::RFC2396::hostname$/, - msgFail => '__badDomainName__', - }, - samlCommonDomainCookieReader => { - type => 'text', - test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, - msgFail => '__badUrl__', - }, - samlCommonDomainCookieWriter => { - type => 'text', - test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, - msgFail => '__badUrl__', - }, - samlRelayStateTimeout => { - type => 'int', - default => 600, - documentation => 'SAML timeout of relay state', - }, - samlUseQueryStringSpecific => { - default => 0, - type => 'bool', - documentation => 'SAML use specific method for query_string', - }, - samlIDPSSODescriptorWantAuthnRequestsSigned => { - type => 'bool', - default => 1, - documentation => 'SAML IDP want authn request signed', - }, - samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;' - . '#PORTAL#/saml/singleSignOn;', - documentation => 'SAML IDP SSO HTTP Redirect', - }, - samlIDPSSODescriptorSingleSignOnServiceHTTPPost => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' - . '#PORTAL#/saml/singleSignOn;', - documentation => 'SAML IDP SSO HTTP POST', - }, - samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;' - . '#PORTAL#/saml/singleSignOnArtifact;', - documentation => 'SAML IDP SSO HTTP Artifact', - }, - samlIDPSSODescriptorSingleSignOnServiceSOAP => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' - . '#PORTAL#/saml/singleSignOnSOAP;', - documentation => 'SAML IDP SSO SOAP', - }, - samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;' - . '#PORTAL#/saml/singleLogout;' - . '#PORTAL#/saml/singleLogoutReturn', - documentation => 'SAML IDP SLO HTTP Redirect', - }, - samlIDPSSODescriptorSingleLogoutServiceHTTPPost => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' - . '#PORTAL#/saml/singleLogout;' - . '#PORTAL#/saml/singleLogoutReturn', - documentation => 'SAML IDP SLO HTTP POST', - }, - samlIDPSSODescriptorSingleLogoutServiceSOAP => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' - . '#PORTAL#/saml/singleLogoutSOAP;', - documentation => 'SAML IDP SLO SOAP', - }, - samlIDPSSODescriptorArtifactResolutionServiceArtifact => { - type => 'samlAssertion', - default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' - . '#PORTAL#/saml/artifact', - documentation => 'SAML IDP artifact resolution service', - }, - - # Fake attribute: used by manager REST API to agglomerate all nodes - # related to a SAML IDP partner - samlIDPMetaDataNodes => { - type => 'samlIDPMetaDataNodeContainer', - template => 'samlIDPMetaDataNode', - }, - - # Fake attribute: used by manager REST API to agglomerate all nodes - # related to a SAML SP partner - samlSPMetaDataNodes => { - type => 'samlSPMetaDataNodeContainer', - template => 'samlSPMetaDataNode', - }, - - # TODO: split that - # IDP Keys - samlIDPMetaDataExportedAttributes => { - type => 'samlAttributeContainer', - help => 'authsaml.html#exported_attributes', - keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, - keyMsgFail => 'Bad metadata name', - default => ';;;', - }, - samlIDPMetaDataXML => { - type => 'file', - }, - samlIDPMetaDataOptions => { - type => 'keyTextContainer', - keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, - keyMsgFail => 'Bad metadata name', - }, - samlIDPMetaDataOptionsNameIDFormat => { - type => 'select', - select => [ - { k => '', v => '' }, - { k => 'unspecified', v => 'Unspecified' }, - { k => 'email', v => 'Email' }, - { k => 'x509', v => 'X509 certificate' }, - { k => 'windows', v => 'Windows' }, - { k => 'kerberos', v => 'Kerberos' }, - { k => 'entity', v => 'Entity' }, - { k => 'persistent', v => 'Persistent' }, - { k => 'transient', v => 'Transient' }, - { k => 'encrypted', v => 'Encrypted' }, - ], - default => '', - }, - samlIDPMetaDataOptionsForceAuthn => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsIsPassive => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsAllowProxiedAuthn => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsAllowLoginFromIDP => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsRequestedAuthnContext => { - type => 'select', - select => [ - { k => '', v => '' }, - { k => 'kerberos', v => 'Kerberos' }, - { - k => 'password-protected-transport', - v => 'Password protected transport' - }, - { k => 'password', v => 'Password' }, - { k => 'tls-client', v => 'TLS client certificate' }, - ], - default => '', - }, - samlIDPMetaDataOptionsAdaptSessionUtime => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsForceUTF8 => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsSignSSOMessage => { - type => 'trool', - default => -1, - }, - samlIDPMetaDataOptionsCheckSSOMessageSignature => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsSignSLOMessage => { - type => 'trool', - default => -1, - }, - samlIDPMetaDataOptionsCheckSLOMessageSignature => { - type => 'bool', - default => 0, - }, - samlIDPMetaDataOptionsSSOBinding => { - type => 'select', - select => [ - { k => '', v => '' }, - { k => 'http-post', v => 'POST' }, - { k => 'http-redirect', v => 'Redirect' }, - { k => 'http-soap', v => 'SOAP' }, - { k => 'artifact-get', v => 'Artifact GET' }, - { k => 'artifact-post', v => 'Artifact POST' }, - ], - default => '', - }, - samlIDPMetaDataOptionsSLOBinding => { - type => 'text', - }, - samlIDPMetaDataOptionsEncryptionMode => { - type => 'select', - select => [ - { k => 'none', v => 'None' }, - { k => 'nameid', v => 'Name ID' }, - { k => 'assertion', v => 'Assertion' }, - ], - default => 'none', - }, - samlIDPMetaDataOptionsCheckConditions => { - type => 'bool', - default => 0, - }, - - # SP keys - samlSPMetaDataExportedAttributes => { - type => 'samlAttributeContainer', - help => 'idpsaml.html#exported_attributes', - keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, - keyMsgFail => 'Bad metadata name', - default => ';;;', - }, - samlSPMetaDataXML => { - type => 'file', - }, - samlSPMetaDataOptions => { - type => 'keyTextContainer', - keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, - keyMsgFail => 'Bad metadata name', - }, - samlSPSSODescriptorAuthnRequestsSigned => { - default => 1, - type => 'bool', - documentation => 'SAML SP AuthnRequestsSigned', - }, - samlSPSSODescriptorWantAssertionsSigned => { - default => 1, - type => 'bool', - documentation => 'SAML SP WantAssertionsSigned', - }, - samlSPSSODescriptorSingleLogoutServiceHTTPRedirect => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;' - . '#PORTAL#/saml/proxySingleLogout;' - . '#PORTAL#/saml/proxySingleLogoutReturn', - documentation => 'SAML SP SLO HTTP Redirect', - }, - samlSPSSODescriptorSingleLogoutServiceHTTPPost => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' - . '#PORTAL#/saml/proxySingleLogout;' - . '#PORTAL#/saml/proxySingleLogoutReturn', - documentation => 'SAML SP SLO HTTP POST', - }, - samlSPSSODescriptorSingleLogoutServiceSOAP => { - type => 'samlService', - default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' - . '#PORTAL#/saml/proxySingleLogoutSOAP;', - documentation => 'SAML SP SLO SOAP', - }, - samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => { - type => 'samlAssertion', - default => - '1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;' - . '#PORTAL#/saml/proxySingleSignOnArtifact', - documentation => 'SAML SP ACS HTTP artifact', - }, - samlSPSSODescriptorAssertionConsumerServiceHTTPPost => { - type => 'samlAssertion', - default => '0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' - . '#PORTAL#/saml/proxySingleSignOnPost', - documentation => 'SAML SP ACS HTTP POST', - }, - samlSPSSODescriptorArtifactResolutionServiceArtifact => { - type => 'samlAssertion', - default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' - . '#PORTAL#/saml/artifact', - documentation => 'SAML SP artifact resolution service ', - }, - samlSPMetaDataOptionsNameIDFormat => { - type => 'select', - select => [ - { k => '', v => '' }, - { k => 'unspecified', v => 'Unspecified' }, - { k => 'email', v => 'Email' }, - { k => 'x509', v => 'X509 certificate' }, - { k => 'windows', v => 'Windows' }, - { k => 'kerberos', v => 'Kerberos' }, - { k => 'entity', v => 'Entity' }, - { k => 'persistent', v => 'Persistent' }, - { k => 'transient', v => 'Transient' }, - { k => 'encrypted', v => 'Encrypted' }, - ], - default => '', - }, - samlSPMetaDataOptionsNameIDSessionKey => { - type => 'text', - }, - samlSPMetaDataOptionsOneTimeUse => { - type => 'bool', - default => 0, - }, - samlSPMetaDataOptionsSessionNotOnOrAfterTimeout => { - type => 'int', - default => 72000, - }, - samlSPMetaDataOptionsNotOnOrAfterTimeout => { - type => 'int', - default => 72000, - }, - samlSPMetaDataOptionsSignSSOMessage => { - type => 'trool', - default => -1, - }, - samlSPMetaDataOptionsCheckSSOMessageSignature => { - type => 'bool', - default => 0, - }, - samlSPMetaDataOptionsSignSLOMessage => { - type => 'trool', - default => -1, - }, - samlSPMetaDataOptionsCheckSLOMessageSignature => { - type => 'bool', - default => 0, - }, - samlSPMetaDataOptionsEncryptionMode => { - type => 'select', - select => [ - { k => 'none', v => 'None' }, - { k => 'nameid', v => 'Name ID' }, - { k => 'assertion', v => 'Assertion' }, - ], - default => 'none', - }, - samlSPMetaDataOptionsEnableIDPInitiatedURL => { - type => 'bool', - default => 0, - }, - - # AUTH, USERDB and PASSWORD MODULES - authentication => { - type => 'select', - select => [ - { k => 'Apache', v => 'Apache' }, - { k => 'AD', v => 'Active Directory' }, - { k => 'BrowserID', v => 'BrowserID (Mozilla Persona)' }, - { k => 'Choice', v => 'authChoice' }, - { k => 'CAS', v => 'Central Authentication Service (CAS)' }, - { k => 'DBI', v => 'Database (DBI)' }, - { k => 'Demo', v => 'Demonstration' }, - { k => 'Facebook', v => 'Facebook' }, - { k => 'Google', v => 'Google' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Multi', v => 'Multiple' }, - { k => 'Null', v => 'None' }, - { k => 'OpenID', v => 'OpenID' }, - { k => 'OpenIDConnect', v => 'OpenID Connect' }, - { k => 'Proxy', v => 'Proxy' }, - { k => 'Radius', v => 'Radius' }, - { k => 'Remote', v => 'Remote' }, - { k => 'SAML', v => 'SAML v2' }, - { k => 'Slave', v => 'Slave' }, - { k => 'SSL', v => 'SSL' }, - { k => 'Twitter', v => 'Twitter' }, - { k => 'WebID', v => 'WebID' }, - { k => 'Yubikey', v => 'Yubikey' }, - ], - default => 'Demo', - documentation => 'Authentication module', - }, - userDB => { - type => 'select', - select => [ - { k => 'AD', v => 'Active Directory' }, - { k => 'DBI', v => 'Database (DBI)' }, - { k => 'Choice', v => 'authChoice' }, - { k => 'Demo', v => 'Demonstration' }, - { k => 'Facebook', v => 'Facebook' }, - { k => 'Google', v => 'Google' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Multi', v => 'Multiple' }, - { k => 'Null', v => 'None' }, - { k => 'OpenID', v => 'OpenID' }, - { k => 'OpenIDConnect', v => 'OpenID Connect' }, - { k => 'Proxy', v => 'Proxy' }, - { k => 'Remote', v => 'Remote' }, - { k => 'SAML', v => 'SAML v2' }, - { k => 'Slave', v => 'Slave' }, - { k => 'WebID', v => 'WebID' }, - ], - default => 'Demo', - documentation => 'User module', - }, - passwordDB => { - type => 'select', - select => [ - { k => 'AD', v => 'Active Directory' }, - { k => 'Choice', v => 'authChoice' }, - { k => 'DBI', v => 'Database (DBI)' }, - { k => 'Demo', v => 'Demonstration' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Null', v => 'None' }, - ], - default => 'Demo', - documentation => 'Password module', - }, - - # DEMO - demoExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => { cn => 'cn', mail => 'mail', uid => 'uid', }, - documentation => 'Demo exported variables', - }, - - # AD - ADPwdExpireWarning => { - type => 'int', - default => 0, - documentation => 'AD password expire warning', - }, - ADPwdMaxAge => { - type => 'int', - default => 0, - documentation => 'AD password max age', - }, - - # LDAP - managerDn => { - type => 'text', - test => qr/^(?:\w+=.*)?$/, - msgFail => '__badValue__', - default => '', - documentation => 'LDAP manager DN', - }, - managerPassword => { - type => 'password', - test => qr/^\S*$/, - msgFail => '__badValue__', - default => '', - documentation => 'LDAP manager Password', - }, - ldapAuthnLevel => { - type => 'int', - default => 2, - documentation => 'LDAP authentication level', - }, - ldapBase => { - type => 'text', - test => qr/^(?:\w+=.*|)$/, - msgFail => '__badValue__', - default => 'dc=example,dc=com', - documentation => 'LDAP search base', - }, - ldapExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => { cn => 'cn', mail => 'mail', uid => 'uid', }, - documentation => 'LDAP exported variables', - }, - ldapPort => { - type => 'int', - default => 389, - documentation => 'LDAP port', - }, - ldapServer => { - type => 'text', - 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; + 'keyTest' => +'(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)', + 'msgFail' => '__badHostname__', + 'type' => 'ruleContainer' + }, + 'loginHistoryEnabled' => { + 'default' => 1, + 'type' => 'bool' + }, + 'logoutServices' => { + 'default' => {}, + 'type' => 'keyTextContainer' + }, + 'macros' => { + 'default' => {}, + 'keyTest' => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/, + 'test' => $VAR1->{'grantSessionRules'}{'keyTest'}, + 'type' => 'keyTextContainer' + }, + 'mailBody' => { + 'type' => 'longtext' + }, + 'mailCharset' => { + 'default' => 'utf-8', + 'type' => 'text' + }, + 'mailConfirmBody' => { + 'type' => 'longtext' + }, + 'mailConfirmSubject' => { + 'default' => '[LemonLDAP::NG] Password reset confirmation', + 'type' => 'text' + }, + 'mailFrom' => { + 'default' => 'noreply@example.com', + 'type' => 'text' + }, + 'mailLDAPFilter' => { + 'type' => 'text' + }, + 'mailOnPasswordChange' => { + 'default' => 0, + 'type' => 'bool' + }, + 'mailReplyTo' => { + 'type' => 'text' + }, + 'mailSessionKey' => { + 'default' => 'mail', + 'type' => 'text' + }, + 'mailSubject' => { + 'default' => '[LemonLDAP::NG] Your new password', + 'type' => 'text' + }, + 'mailTimeout' => { + 'default' => 0, + 'type' => 'int' + }, + 'mailUrl' => { + 'default' => 'http://auth.example.com/mail.pl', + 'type' => 'text' + }, + 'maintenance' => { + 'default' => 0, + 'type' => 'bool' + }, + 'managerDn' => { + 'default' => '', + 'msgFail' => '__badValue__', + 'test' => qr/^(?:\w+=.*)?$/, + 'type' => 'text' + }, + 'managerPassword' => { + 'default' => '', + 'msgFail' => '__badValue__', + 'test' => qr/^\S*$/, + 'type' => 'password' + }, + 'multiAuthStack' => { + 'type' => 'authParamsText' + }, + 'multiUserDBStack' => { + 'type' => 'authParamsText' + }, + 'multiValuesSeparator' => { + 'default' => '; ', + 'type' => 'authParamsText' + }, + 'notification' => { + 'default' => 0, + 'type' => 'bool' + }, + 'notificationStorage' => { + 'default' => 'File', + 'type' => 'text' + }, + 'notificationStorageOptions' => { + 'default' => { + 'dirName' => '/var/lib/lemonldap-ng/notifications' }, - default => 'ldap://localhost', - documentation => 'LDAP server (host or URI)', + 'type' => 'keyTextContainer' }, - ldapPwdEnc => { - type => 'text', - test => qr/^[a-zA-Z0-9_][a-zA-Z0-9_\-]*[a-zA-Z0-9_]$/, - msgFail => '__badEncoding__', - default => 'utf-8', - documentation => 'LDAP password encoding', + 'notificationWildcard' => { + 'default' => 'allusers', + 'type' => 'text' }, - ldapUsePasswordResetAttribute => { - default => 0, - type => 'bool', - default => 1, - documentation => 'LDAP store reset flag in an attribute', + 'notificationXSLTfile' => { + 'type' => 'text' }, - ldapPasswordResetAttribute => { - type => 'text', - default => 'pwdReset', - documentation => 'LDAP password reset attribute', + 'notifyDeleted' => { + 'default' => 1, + 'type' => 'bool' }, - ldapPasswordResetAttributeValue => { - type => 'text', - default => 'TRUE', - documentation => 'LDAP password reset value', + 'notifyOther' => { + 'default' => 0, + 'type' => 'bool' }, - ldapPpolicyControl => { - default => 0, - type => 'bool', + 'nullAuthnLevel' => { + 'default' => 2, + 'type' => 'int' }, - ldapSetPassword => { - default => 0, - type => 'bool', + 'oidcAuthnLevel' => { + 'default' => 1, + 'type' => 'int' }, - ldapChangePasswordAsUser => { - default => 0, - type => 'bool', + 'oidcOPMetaDataExportedVars' => { + 'type' => 'keyTextContainer' }, - mailLDAPFilter => { type => 'text', }, - LDAPFilter => { type => 'text', }, - AuthLDAPFilter => { type => 'text', }, - ldapGroupRecursive => { - default => 0, - type => 'bool', - documentation => 'LDAP recursive search in groups', + 'oidcOPMetaDataJSON' => { + 'type' => 'file' }, - ldapGroupObjectClass => { - type => 'text', - default => 'groupOfNames', - documentation => 'LDAP object class of groups', + 'oidcOPMetaDataJWKS' => { + 'type' => 'file' }, - ldapGroupBase => { type => 'text', }, - ldapGroupAttributeName => { - type => 'text', - default => 'member', - documentation => 'LDAP attribute name for member in groups', + 'oidcOPMetaDataNodes' => { + 'type' => 'oidcOPMetaDataNodeContainer' }, - ldapGroupAttributeNameUser => { - type => 'text', - default => 'dn', - documentation => -'LDAP attribute name in user entry referenced as member in groups', + 'oidcOPMetaDataOptions' => { + 'type' => 'subContainer' }, - ldapGroupAttributeNameSearch => { - type => 'text', - default => 'cn', - documentation => 'LDAP attributes to search in groups', + 'oidcOPMetaDataOptionsAcrValues' => { + 'type' => 'text' }, - ldapGroupAttributeNameGroup => { - type => 'text', - default => 'dn', - documentation => -'LDAP attribute name in group entry referenced as member in groups', + 'oidcOPMetaDataOptionsCheckJWTSignature' => { + 'type' => 'bool' }, - ldapTimeout => { - type => 'int', - default => 120, - documentation => 'LDAP connection timeout', + 'oidcOPMetaDataOptionsClientID' => { + 'type' => 'text' }, - ldapVersion => { - type => 'int', - default => 3, - documentation => 'LDAP protocol version', + 'oidcOPMetaDataOptionsClientSecret' => { + 'type' => 'password' }, - ldapRaw => { type => 'text', }, - - # SSL - SSLAuthnLevel => { - type => 'int', - default => 5, - documentation => 'SSL authentication level', + 'oidcOPMetaDataOptionsConfigurationURI' => { + 'type' => 'text' }, - SSLVar => { type => 'text', }, - - # CAS - CAS_authnLevel => { - type => 'int', - default => 1, - documentation => 'CAS authentication level', + 'oidcOPMetaDataOptionsDisplay' => { + 'type' => 'text' }, - CAS_url => { - type => 'text', - test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, - msgFail => '__badUrl__', + 'oidcOPMetaDataOptionsDisplayName' => { + 'type' => 'text' }, - CAS_CAFile => { type => 'text', }, - CAS_renew => { type => 'bool', }, - CAS_gateway => { type => 'bool', }, - CAS_pgtFile => { - type => 'text', - default => '/tmp/pgt.txt', - documentation => 'CAS PGT file', + 'oidcOPMetaDataOptionsIcon' => { + 'type' => 'text' }, - CAS_proxiedServices => { - type => 'keyTextContainer', - keyTest => qr/^\w+$/, - keyMsgFail => 'Bad CAS proxied service identifier', + 'oidcOPMetaDataOptionsIDTokenMaxAge' => { + 'type' => 'int' }, - - # Radius - radiusAuthnLevel => { - type => 'int', - default => 3, - documentation => 'Radius authentication level', + 'oidcOPMetaDataOptionsJWKSTimeout' => { + 'type' => 'int' }, - radiusSecret => { type => 'text', }, - radiusServer => { type => 'text', }, - - # Remote - remotePortal => { type => 'text', }, - remoteGlobalStorage => { - type => 'PerlModule', - default => 'Lemonldap::NG::Common::Apache::Session::SOAP', - documentation => 'Remote session backend', + 'oidcOPMetaDataOptionsMaxAge' => { + 'type' => 'int' }, - remoteGlobalStorageOptions => { - type => 'keyTextContainer', - default => { - proxy => 'http://auth.example.com/index.pl/sessions', - ns => - 'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService', - }, - documentation => 'Demo exported variables', + 'oidcOPMetaDataOptionsPrompt' => { + 'type' => 'text' }, - - # Proxy - soapAuthService => { type => 'text', }, - remoteCookieName => { type => 'text', }, - soapSessionService => { type => 'text', }, - - # OpenID - openIdAuthnLevel => { - type => 'int', - default => 1, - documentation => 'OpenID authentication level', + 'oidcOPMetaDataOptionsScope' => { + 'type' => 'text' }, - openIdSecret => { type => 'text', }, - openIdExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => {}, - documentation => 'OpenID exported variables', + 'oidcOPMetaDataOptionsTokenEndpointAuthMethod' => { + 'type' => 'text' }, - 'openIdIDPList' => { 'type' => 'blackWhiteList', default => '0;' }, - - # Google - googleAuthnLevel => { - type => 'int', - default => 1, - documentation => 'Google authentication level', + 'oidcOPMetaDataOptionsUiLocales' => { + 'type' => 'text' }, - googleExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => {}, - documentation => 'Google exported variables', + 'oidcOPMetaDataOptionsUseNonce' => { + 'type' => 'bool' }, - - # Facebook - facebookAuthnLevel => { - type => 'int', - default => 1, - documentation => 'Facebook authentication level', + 'oidcRPCallbackGetParam' => { + 'default' => 'openidconnectcallback', + 'type' => 'text' }, - facebookAppId => { type => 'text', }, - facebookAppSecret => { type => 'text', }, - facebookExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => {}, - documentation => 'Facebook exported variables', + 'oidcRPMetaDataExportedVars' => { + 'type' => 'keyTextContainer' }, - - # Twitter - twitterAuthnLevel => { - type => 'int', - default => 1, - documentation => 'Twitter authentication level', + 'oidcRPMetaDataNodes' => { + 'type' => 'oidcRPMetaDataNodeContainer' }, - twitterKey => { type => 'text', }, - twitterSecret => { type => 'text', }, - twitterAppName => { type => 'text', }, - - # WebID - webIDAuthnLevel => { - type => 'int', - default => 1, - documentation => 'WebID authentication level', + 'oidcRPMetaDataOptions' => { + 'type' => 'subContainer' }, - webIDWhitelist => { type => 'text', }, - webIDExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => {}, - documentation => 'WebID exported variables', + 'oidcRPMetaDataOptionsAccessTokenExpiration' => { + 'type' => 'int' }, - - # DBI - dbiAuthnLevel => { - type => 'int', - default => 2, - documentation => 'DBI authentication level', + 'oidcRPMetaDataOptionsClientID' => { + 'type' => 'text' }, - dbiAuthChain => { type => 'text', }, - dbiAuthUser => { type => 'text', }, - dbiAuthPassword => { type => 'password', }, - dbiUserChain => { type => 'text', }, - dbiUserUser => { type => 'text', }, - dbiUserPassword => { type => 'password', }, - dbiAuthTable => { type => 'text', }, - dbiUserTable => { type => 'text', }, - dbiAuthLoginCol => { type => 'text', }, - dbiAuthPasswordCol => { type => 'text', }, - dbiPasswordMailCol => { type => 'text', }, - userPivot => { type => 'text', }, - dbiAuthPasswordHash => - { type => 'text', help => 'authdbi.html#password', }, - dbiExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => {}, - documentation => 'DBI exported variables', + 'oidcRPMetaDataOptionsClientSecret' => { + 'type' => 'password' }, - - # Apache - apacheAuthnLevel => { - type => 'int', - default => 4, - documentation => 'Apache authentication level', + 'oidcRPMetaDataOptionsDisplayName' => { + 'type' => 'text' }, - - # Null - nullAuthnLevel => { - type => 'int', - default => 2, - documentation => 'Null authentication level', + 'oidcRPMetaDataOptionsExtraClaims' => { + 'type' => 'keyTextContainer' }, - - # Slave - slaveAuthnLevel => { - type => 'int', - default => 2, - documentation => 'Slave authentication level', + 'oidcRPMetaDataOptionsIcon' => { + 'type' => 'text' }, - slaveUserHeader => { type => 'text', }, - slaveExportedVars => { - type => 'keyTextContainer', - keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, - keyMsgFail => 'Bad variable name', - test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, - msgFail => '__badValue__', - default => {}, - documentation => 'Slave exported variables', + 'oidcRPMetaDataOptionsIDTokenExpiration' => { + 'type' => 'int' }, - slaveMasterIP => { - type => 'text', - test => qr/^$Regexp::Common::URI::RFC2396::IPv4address$/, - msgFail => '__badIPv4Address__', + 'oidcRPMetaDataOptionsIDTokenSignAlg' => { + 'type' => 'text' }, - - # Choice - authChoiceParam => { - type => 'text', - default => 'lmAuth', - documentation => 'Applications list', + 'oidcRPMetaDataOptionsRedirectUris' => { + 'type' => 'text' }, - authChoiceModules => { - type => 'authChoiceContainer', - keyTest => qr/^(\d*)?[a-zA-Z0-9_]+$/, - keyMsgFail => 'Bad choice key', - select => [ - [ - { k => 'Apache', v => 'Apache' }, - { k => 'AD', v => 'Active Directory' }, - { k => 'BrowserID', v => 'BrowserID (Mozilla Persona)' }, - { k => 'CAS', v => 'Central Authentication Service (CAS)' }, - { k => 'DBI', v => 'Database (DBI)' }, - { k => 'Facebook', v => 'Facebook' }, - { k => 'Google', v => 'Google' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Null', v => 'None' }, - { k => 'OpenID', v => 'OpenID' }, - { k => 'OpenIDConnect', v => 'OpenID Connect' }, - { k => 'Proxy', v => 'Proxy' }, - { k => 'Radius', v => 'Radius' }, - { k => 'Remote', v => 'Remote' }, - { k => 'SAML', v => 'SAML v2' }, - { k => 'Slave', v => 'Slave' }, - { k => 'SSL', v => 'SSL' }, - { k => 'Twitter', v => 'Twitter' }, - { k => 'WebID', v => 'WebID' }, - { k => 'Yubikey', v => 'Yubikey' } - ], - [ - { k => 'AD', v => 'Active Directory' }, - { k => 'DBI', v => 'Database (DBI)' }, - { k => 'Facebook', v => 'Facebook' }, - { k => 'Google', v => 'Google' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Null', v => 'None' }, - { k => 'OpenID', v => 'OpenID' }, - { k => 'OpenIDConnect', v => 'OpenID Connect' }, - { k => 'Proxy', v => 'Proxy' }, - { k => 'Remote', v => 'Remote' }, - { k => 'SAML', v => 'SAML v2' }, - { k => 'Slave', v => 'Slave' }, - { k => 'WebID', v => 'WebID' } - ], - [ - { k => 'AD', v => 'Active Directory' }, - { k => 'Choice', v => 'authChoice' }, - { k => 'DBI', v => 'Database (DBI)' }, - { k => 'LDAP', v => 'LDAP' }, - { k => 'Null', v => 'None' } - ] - ], + 'oidcRPMetaDataOptionsUserIDAttr' => { + 'type' => 'text' }, - - # Multi - multiAuthStack => { - type => 'authParamsText', + 'oidcRPStateTimeout' => { + 'default' => 600, + 'type' => 'int' }, - multiUserDBStack => { - type => 'authParamsText', + 'oidcServiceAllowAuthorizationCodeFlow' => { + 'default' => '1', + 'type' => 'bool' }, - multiValuesSeparator => { - type => 'authParamsText', - default => '; ', - documentation => 'Separator for multiple values', + 'oidcServiceAllowDynamicRegistration' => { + 'default' => '0', + 'type' => 'bool' }, - - # Yubikey - yubikeyAuthnLevel => { - type => 'int', - default => 3, - documentation => 'Yubikey authentication level', + 'oidcServiceAllowHybridFlow' => { + 'default' => '0', + 'type' => 'bool' }, - yubikeyClientID => { type => 'text', }, - yubikeySecretKey => { type => 'text', }, - yubikeyPublicIDSize => { - type => 'int', - default => 12, - documentation => 'Yubikey public ID size', + 'oidcServiceAllowImplicitFlow' => { + 'default' => '0', + 'type' => 'bool' }, - - # BrowserID - browserIdAuthnLevel => { - type => 'int', - default => 1, - documentation => 'Browser ID authentication level', + 'oidcServiceKeyIdSig' => { + 'type' => 'text' }, - browserIdAutoLogin => { type => 'bool', }, - browserIdVerificationURL => { type => 'text', }, - browserIdSiteName => { type => 'text', }, - browserIdSiteLogo => { type => 'text', }, - browserIdBackgroundColor => { type => 'text', }, - - # OpenID Connect auth params - oidcAuthnLevel => { - type => 'int', - default => 1, - documentation => 'OpenID Connect authentication level', - }, - oidcRPCallbackGetParam => { - type => 'text', - default => 'openidconnectcallback', - documentation => 'OpenID Connect Callback GET URLparameter', - }, - oidcRPStateTimeout => { - type => 'int', - default => 600, - documentation => 'OpenID Connect Timeout of state sessions', - }, - - # OpenID Connect service - oidcServiceMetaDataIssuer => { - type => 'text', - documentation => 'OpenID Connect end session endpoint', - }, - oidcServiceMetaDataAuthorizeURI => { - type => 'text', - default => 'authorize', - documentation => 'OpenID Connect authorizaton endpoint', - }, - oidcServiceMetaDataTokenURI => { - type => 'text', - default => 'token', - documentation => 'OpenID Connect token endpoint', - }, - oidcServiceMetaDataUserInfoURI => { - type => 'text', - default => 'userinfo', - documentation => 'OpenID Connect user info endpoint', - }, - oidcServiceMetaDataJWKSURI => { - type => 'text', - default => 'jwks', - documentation => 'OpenID Connect JWKS endpoint', - }, - oidcServiceMetaDataRegistrationURI => { - type => 'text', - default => 'register', - documentation => 'OpenID Connect registration endpoint', - }, - oidcServiceMetaDataEndSessionURI => { - type => 'text', - default => 'logout', - documentation => 'OpenID Connect end session endpoint', - }, - oidcServiceMetaDataCheckSessionURI => { - type => 'text', - default => 'checksession', - documentation => 'OpenID Connect check session iframe', - }, - oidcServiceMetaDataAuthnContext => { - type => 'keyTextContainer', - default => { + 'oidcServiceMetaDataAuthnContext' => { + 'default' => { 'loa-1' => 1, 'loa-2' => 2, 'loa-3' => 3, 'loa-4' => 4, - 'loa-5' => 5, + 'loa-5' => 5 }, - documentation => 'OpenID Connect Authentication Context Class Ref', + 'type' => 'keyTextContainer' }, - oidcServicePrivateKeySig => { type => 'RSAPrivateKey', }, - oidcServicePublicKeySig => { type => 'RSAPublicKey', }, - oidcServiceKeyIdSig => { - type => 'text', - documentation => 'OpenID Connect Signature Key ID', + 'oidcServiceMetaDataAuthorizeURI' => { + 'default' => 'authorize', + 'type' => 'text' }, - oidcServiceAllowDynamicRegistration => { - type => 'bool', - default => '0', - documentation => 'OpenID Connect allow dynamic client registration', + 'oidcServiceMetaDataCheckSessionURI' => { + 'default' => 'checksession', + 'type' => 'text' }, - oidcServiceAllowAuthorizationCodeFlow => { - type => 'bool', - default => '1', - documentation => 'OpenID Connect allow authorization code flow', + 'oidcServiceMetaDataEndSessionURI' => { + 'default' => 'logout', + 'type' => 'text' }, - oidcServiceAllowImplicitFlow => { - type => 'bool', - default => '0', - documentation => 'OpenID Connect allow implicit flow', + 'oidcServiceMetaDataIssuer' => { + 'type' => 'text' }, - oidcServiceAllowHybridFlow => { - type => 'bool', - default => '0', - documentation => 'OpenID Connect allow hybrid flow', + 'oidcServiceMetaDataJWKSURI' => { + 'default' => 'jwks', + 'type' => 'text' }, - oidcStorage => { type => 'PerlModule', }, - oidcStorageOptions => { - type => 'keyTextContainer', + 'oidcServiceMetaDataRegistrationURI' => { + 'default' => 'register', + 'type' => 'text' }, - - # OpenID Connect metadata nodes - oidcOPMetaDataNodes => - { type => 'oidcOPMetaDataNodeContainer', help => 'oidcop.html', }, - oidcRPMetaDataNodes => - { type => 'oidcRPMetaDataNodeContainer', help => 'oidcrp.html', }, - oidcOPMetaDataOptions => { type => 'subContainer', }, - oidcRPMetaDataOptions => { type => 'subContainer', }, - - # OpenID Connect providers - oidcOPMetaDataJSON => { type => 'file', }, - oidcOPMetaDataJWKS => { type => 'file', }, - oidcOPMetaDataExportedVars => { type => 'keyTextContainer', }, - oidcOPMetaDataOptionsConfigurationURI => { type => 'text', }, - oidcOPMetaDataOptionsJWKSTimeout => { type => 'int', }, - oidcOPMetaDataOptionsClientID => { type => 'text', }, - oidcOPMetaDataOptionsClientSecret => { type => 'password', }, - oidcOPMetaDataOptionsScope => { type => 'text', }, - oidcOPMetaDataOptionsDisplay => { type => 'text', }, - oidcOPMetaDataOptionsPrompt => { type => 'text', }, - oidcOPMetaDataOptionsMaxAge => { type => 'int', }, - oidcOPMetaDataOptionsUiLocales => { type => 'text', }, - oidcOPMetaDataOptionsAcrValues => { type => 'text', }, - oidcOPMetaDataOptionsTokenEndpointAuthMethod => { type => 'text', }, - oidcOPMetaDataOptionsCheckJWTSignature => { type => 'bool', }, - oidcOPMetaDataOptionsIDTokenMaxAge => { type => 'int', }, - oidcOPMetaDataOptionsUseNonce => { type => 'bool', }, - oidcOPMetaDataOptionsDisplayName => { type => 'text', }, - oidcOPMetaDataOptionsIcon => { type => 'text', }, - - # OpenID Connect relying parties - oidcRPMetaDataExportedVars => { type => 'keyTextContainer', }, - oidcRPMetaDataOptionsClientID => { type => 'text', }, - oidcRPMetaDataOptionsClientSecret => { type => 'password', }, - oidcRPMetaDataOptionsDisplayName => { type => 'text', }, - oidcRPMetaDataOptionsIcon => { type => 'text', }, - oidcRPMetaDataOptionsUserIDAttr => { type => 'text', }, - oidcRPMetaDataOptionsIDTokenSignAlg => { type => 'text', }, - oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int', }, - oidcRPMetaDataOptionsAccessTokenExpiration => { type => 'int', }, - oidcRPMetaDataOptionsRedirectUris => { type => 'text', }, - oidcRPMetaDataOptionsExtraClaims => { type => 'keyTextContainer', }, - + 'oidcServiceMetaDataTokenURI' => { + 'default' => 'token', + 'type' => 'text' + }, + 'oidcServiceMetaDataUserInfoURI' => { + 'default' => 'userinfo', + 'type' => 'text' + }, + 'oidcServicePrivateKeySig' => { + 'type' => 'RSAPrivateKey' + }, + 'oidcServicePublicKeySig' => { + 'type' => 'RSAPublicKey' + }, + 'oidcStorage' => { + 'type' => 'text' + }, + 'oidcStorageOptions' => { + 'type' => 'keyTextContainer' + }, + 'openIdAttr' => { + 'type' => 'text' + }, + 'openIdAuthnLevel' => { + 'default' => 1, + 'type' => 'int' + }, + 'openIdExportedVars' => { + 'default' => {}, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'openIdIDPList' => { + 'default' => '0;', + 'type' => 'blackWhiteList' + }, + 'openIdIssuerSecret' => { + 'type' => 'text' + }, + 'openIdSecret' => { + 'type' => 'text' + }, + 'openIdSPList' => { + 'default' => '0;', + 'type' => 'blackWhiteList' + }, + 'openIdSreg_country' => { + 'type' => 'text' + }, + 'openIdSreg_dob' => { + 'type' => 'text' + }, + 'openIdSreg_email' => { + 'default' => 'mail', + 'type' => 'text' + }, + 'openIdSreg_fullname' => { + 'default' => 'cn', + 'type' => 'text' + }, + 'openIdSreg_gender' => { + 'type' => 'text' + }, + 'openIdSreg_language' => { + 'type' => 'text' + }, + 'openIdSreg_nickname' => { + 'default' => 'uid', + 'type' => 'text' + }, + 'openIdSreg_postcode' => { + 'type' => 'text' + }, + 'openIdSreg_timezone' => { + 'default' => '_timezone', + 'type' => 'text' + }, + 'passwordDB' => { + 'default' => 'Demo', + 'type' => 'select' + }, + 'persistentStorage' => { + 'type' => 'text' + }, + 'persistentStorageOptions' => { + 'type' => 'keyTextContainer' + }, + 'port' => { + 'type' => 'int' + }, + 'portal' => { + 'default' => 'http://auth.example.com/', + 'type' => 'text' + }, + 'portalAntiFrame' => { + 'default' => 1, + 'type' => 'bool' + }, + 'portalCheckLogins' => { + 'default' => 1, + 'type' => 'bool' + }, + 'portalDisplayAppslist' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'portalDisplayChangePassword' => { + 'default' => '$_auth =~ /^(LDAP|DBI|Demo)$/', + 'type' => 'boolOrExpr' + }, + 'portalDisplayLoginHistory' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'portalDisplayLogout' => { + 'default' => 1, + 'type' => 'boolOrExpr' + }, + 'portalDisplayRegister' => { + 'default' => 1, + 'type' => 'bool' + }, + 'portalDisplayResetPassword' => { + 'default' => 1, + 'type' => 'bool' + }, + 'portalForceAuthn' => { + 'default' => 0, + 'type' => 'bool' + }, + 'portalForceAuthnInterval' => { + 'default' => 0, + 'type' => 'int' + }, + 'portalOpenLinkInNewWindow' => { + 'default' => 0, + 'type' => 'bool' + }, + 'portalPingInterval' => { + 'default' => 60000, + 'type' => 'int' + }, + 'portalRequireOldPassword' => { + 'default' => 1, + 'type' => 'bool' + }, + 'portalSkin' => { + 'default' => 'bootstrap', + 'type' => 'portalskin' + }, + 'portalSkinBackground' => { + 'type' => 'portalskinbackground' + }, + 'portalSkinRules' => { + 'keyTest' => $VAR1->{'grantSessionRules'}{'keyTest'}, + 'msgFail' => '__badValue__', + 'test' => qr/^\w+$/, + 'type' => 'keyTextContainer' + }, + 'portalUserAttr' => { + 'default' => '_user', + 'type' => 'text' + }, + 'post' => { + 'keyTest' => +'(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)', + 'type' => 'postContainer' + }, + 'protection' => { + 'default' => 'none', + 'msgFail' => '__authorizedValues__: none authenticate manager', + 'test' => qr/^(?:none|authenticate|manager|)$/, + 'type' => 'text' + }, + 'radiusAuthnLevel' => { + 'default' => 3, + 'type' => 'int' + }, + 'radiusSecret' => { + 'type' => 'text' + }, + 'radiusServer' => { + 'type' => 'text' + }, + 'randomPasswordRegexp' => { + 'default' => '[A-Z]{3}[a-z]{5}.\\d{2}', + 'type' => 'text' + }, + 'redirectFormMethod' => { + 'default' => 'get', + 'type' => 'select' + }, + 'registerConfirmSubject' => { + 'default' => '[LemonLDAP::NG] Account register confirmation', + 'type' => 'text' + }, + 'registerDB' => { + 'default' => 'Demo', + 'type' => 'select' + }, + 'registerDoneSubject' => { + 'default' => '[LemonLDAP::NG] Your new account', + 'type' => 'text' + }, + 'registerTimeout' => { + 'default' => 0, + 'type' => 'int' + }, + 'registerUrl' => { + 'default' => 'http://auth.example.com/register.pl', + 'type' => 'text' + }, + 'reloadUrls' => { + 'keyTest' => +qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))$/, + 'msgFail' => '__badUrl__', + 'test' => +qr/^(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)$/, + 'type' => 'keyTextContainer' + }, + 'remoteCookieName' => { + 'type' => 'text' + }, + 'remoteGlobalStorage' => { + 'default' => 'Lemonldap::NG::Common::Apache::Session::SOAP', + 'type' => 'text' + }, + 'remoteGlobalStorageOptions' => { + 'default' => { + 'ns' => + 'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService', + 'proxy' => 'http://auth.example.com/index.pl/sessions' + }, + 'type' => 'keyTextContainer' + }, + 'remotePortal' => { + 'type' => 'text' + }, + 'samlAttributeAuthorityDescriptorAttributeServiceSOAP' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;', + 'type' => 'samlService' + }, + 'samlAuthnContextMapKerberos' => { + 'default' => 4, + 'type' => 'int' + }, + 'samlAuthnContextMapPassword' => { + 'default' => 2, + 'type' => 'int' + }, + 'samlAuthnContextMapPasswordProtectedTransport' => { + 'default' => 3, + 'type' => 'int' + }, + 'samlAuthnContextMapTLSClient' => { + 'default' => 5, + 'type' => 'int' + }, + 'samlCommonDomainCookieActivation' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlCommonDomainCookieDomain' => { + 'msgFail' => '__badDomainName__', + 'test' => +qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/, + 'type' => 'text' + }, + 'samlCommonDomainCookieReader' => { + 'msgFail' => '__badUrl__', + 'test' => +qr/^(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)$/, + 'type' => 'text' + }, + 'samlCommonDomainCookieWriter' => { + 'msgFail' => '__badUrl__', + 'test' => +qr/^(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)$/, + 'type' => 'text' + }, + 'samlEntityID' => { + 'default' => '#PORTAL#/saml/metadata', + 'type' => 'text' + }, + 'samlIDPMetaDataExportedAttributes' => { + 'default' => ';;;', + 'keyTest' => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + 'type' => 'samlAttributeContainer' + }, + 'samlIDPMetaDataNodes' => { + 'type' => 'samlIDPMetaDataNodeContainer' + }, + 'samlIDPMetaDataOptions' => { + 'keyTest' => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + 'type' => 'keyTextContainer' + }, + 'samlIDPMetaDataOptionsAdaptSessionUtime' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsAllowLoginFromIDP' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsAllowProxiedAuthn' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsCheckConditions' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsCheckSLOMessageSignature' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsCheckSSOMessageSignature' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsEncryptionMode' => { + 'default' => 'none', + 'type' => 'select' + }, + 'samlIDPMetaDataOptionsForceAuthn' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsForceUTF8' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsIsPassive' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlIDPMetaDataOptionsNameIDFormat' => { + 'default' => '', + 'type' => 'select' + }, + 'samlIDPMetaDataOptionsRequestedAuthnContext' => { + 'default' => '', + 'type' => 'select' + }, + 'samlIDPMetaDataOptionsSignSLOMessage' => { + 'default' => -1, + 'type' => 'trool' + }, + 'samlIDPMetaDataOptionsSignSSOMessage' => { + 'default' => -1, + 'type' => 'trool' + }, + 'samlIDPMetaDataOptionsSLOBinding' => { + 'type' => 'text' + }, + 'samlIDPMetaDataOptionsSSOBinding' => { + 'default' => '', + 'type' => 'select' + }, + 'samlIDPMetaDataXML' => { + 'type' => 'file' + }, + 'samlIdPResolveCookie' => { + 'default' => 'lemonldapidp', + 'type' => 'text' + }, + 'samlIDPSSODescriptorArtifactResolutionServiceArtifact' => { + 'default' => +'1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact', + 'type' => 'samlAssertion' + }, + 'samlIDPSSODescriptorSingleLogoutServiceHTTPPost' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorSingleLogoutServiceSOAP' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/singleLogoutSOAP;', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/singleSignOnArtifact;', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorSingleSignOnServiceHTTPPost' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleSignOn;', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleSignOn;', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorSingleSignOnServiceSOAP' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/singleSignOnSOAP;', + 'type' => 'samlService' + }, + 'samlIDPSSODescriptorWantAuthnRequestsSigned' => { + 'default' => 1, + 'type' => 'bool' + }, + 'samlMetadataForceUTF8' => { + 'default' => 1, + 'type' => 'bool' + }, + 'samlNameIDFormatMapEmail' => { + 'default' => 'mail', + 'type' => 'text' + }, + 'samlNameIDFormatMapKerberos' => { + 'default' => 'uid', + 'type' => 'text' + }, + 'samlNameIDFormatMapWindows' => { + 'default' => 'uid', + 'type' => 'text' + }, + 'samlNameIDFormatMapX509' => { + 'default' => 'mail', + 'type' => 'text' + }, + 'samlOrganizationDisplayName' => { + 'default' => 'Example', + 'type' => 'text' + }, + 'samlOrganizationName' => { + 'default' => 'Example', + 'type' => 'text' + }, + 'samlOrganizationURL' => { + 'default' => 'http://www.example.com', + 'type' => 'text' + }, + 'samlRelayStateTimeout' => { + 'default' => 600, + 'type' => 'int' + }, + 'samlServicePrivateKeyEnc' => { + 'default' => '', + 'type' => 'RSAPrivateKey' + }, + 'samlServicePrivateKeyEncPwd' => { + 'type' => 'password' + }, + 'samlServicePrivateKeySig' => { + 'default' => '', + 'type' => 'RSAPrivateKey' + }, + 'samlServicePrivateKeySigPwd' => { + 'default' => '', + 'type' => 'password' + }, + 'samlServicePublicKeyEnc' => { + 'default' => '', + 'type' => 'RSAPublicKey' + }, + 'samlServicePublicKeySig' => { + 'default' => '', + 'type' => 'RSAPublicKey' + }, + 'samlSPMetaDataExportedAttributes' => { + 'default' => ';;;', + 'keyTest' => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + 'type' => 'samlAttributeContainer' + }, + 'samlSPMetaDataNodes' => { + 'type' => 'samlSPMetaDataNodeContainer' + }, + 'samlSPMetaDataOptions' => { + 'keyTest' => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + 'type' => 'keyTextContainer' + }, + 'samlSPMetaDataOptionsCheckSLOMessageSignature' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlSPMetaDataOptionsCheckSSOMessageSignature' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlSPMetaDataOptionsEnableIDPInitiatedURL' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlSPMetaDataOptionsEncryptionMode' => { + 'default' => 'none', + 'type' => 'select' + }, + 'samlSPMetaDataOptionsNameIDFormat' => { + 'default' => '', + 'type' => 'select' + }, + 'samlSPMetaDataOptionsNameIDSessionKey' => { + 'type' => 'text' + }, + 'samlSPMetaDataOptionsNotOnOrAfterTimeout' => { + 'default' => 72000, + 'type' => 'int' + }, + 'samlSPMetaDataOptionsOneTimeUse' => { + 'default' => 0, + 'type' => 'bool' + }, + 'samlSPMetaDataOptionsSessionNotOnOrAfterTimeout' => { + 'default' => 72000, + 'type' => 'int' + }, + 'samlSPMetaDataOptionsSignSLOMessage' => { + 'default' => -1, + 'type' => 'trool' + }, + 'samlSPMetaDataOptionsSignSSOMessage' => { + 'default' => -1, + 'type' => 'trool' + }, + 'samlSPMetaDataXML' => { + 'type' => 'file' + }, + 'samlSPSSODescriptorArtifactResolutionServiceArtifact' => { + 'default' => +'1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact', + 'type' => 'samlAssertion' + }, + 'samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact' => { + 'default' => +'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact', + 'type' => 'samlAssertion' + }, + 'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' => { + 'default' => +'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost', + 'type' => 'samlAssertion' + }, + 'samlSPSSODescriptorAuthnRequestsSigned' => { + 'default' => 1, + 'type' => 'bool' + }, + 'samlSPSSODescriptorSingleLogoutServiceHTTPPost' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn', + 'type' => 'samlService' + }, + 'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn', + 'type' => 'samlService' + }, + 'samlSPSSODescriptorSingleLogoutServiceSOAP' => { + 'default' => +'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/proxySingleLogoutSOAP;', + 'type' => 'samlService' + }, + 'samlSPSSODescriptorWantAssertionsSigned' => { + 'default' => 1, + 'type' => 'bool' + }, + 'samlStorage' => { + 'type' => 'text' + }, + 'samlStorageOptions' => { + 'type' => 'keyTextContainer' + }, + 'samlUseQueryStringSpecific' => { + 'default' => 0, + 'type' => 'bool' + }, + 'securedCookie' => { + 'default' => 0, + 'type' => 'select' + }, + 'secureTokenAllowOnError' => { + 'default' => 1, + 'type' => 'bool' + }, + 'secureTokenAttribute' => { + 'default' => 'uid', + 'type' => 'text' + }, + 'secureTokenExpiration' => { + 'default' => 60, + 'type' => 'int' + }, + 'secureTokenHeader' => { + 'default' => 'Auth-Token', + 'type' => 'text' + }, + 'secureTokenMemcachedServers' => { + 'default' => '127.0.0.1:11211', + 'type' => 'text' + }, + 'secureTokenUrls' => { + 'default' => '.*', + 'type' => 'text' + }, + 'sessionDataToRemember' => { + 'keyTest' => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/, + 'type' => 'keyTextContainer' + }, + 'singleIP' => { + 'default' => 0, + 'type' => 'bool' + }, + 'singleSession' => { + 'default' => 0, + 'type' => 'bool' + }, + 'singleSessionUserByIP' => { + 'default' => 0, + 'type' => 'bool' + }, + 'singleUserByIP' => { + 'default' => 0, + 'type' => 'bool' + }, + 'slaveAuthnLevel' => { + 'default' => 2, + 'type' => 'int' + }, + 'slaveExportedVars' => { + 'default' => {}, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'slaveMasterIP' => { + 'msgFail' => '__badIPv4Address__', + 'test' => qr/^(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)$/, + 'type' => 'text' + }, + 'slaveUserHeader' => { + 'type' => 'text' + }, + 'SMTPAuthPass' => { + 'type' => 'password' + }, + 'SMTPAuthUser' => { + 'type' => 'text' + }, + 'SMTPServer' => { + 'default' => '', + 'type' => 'text' + }, + 'Soap' => { + 'default' => 0, + 'type' => 'bool' + }, + 'soapAuthService' => { + 'type' => 'text' + }, + 'soapSessionService' => { + 'type' => 'text' + }, + 'SSLAuthnLevel' => { + 'default' => 5, + 'type' => 'int' + }, + 'SSLVar' => { + 'type' => 'text' + }, + 'staticPrefix' => { + 'type' => 'text' + }, + 'storePassword' => { + 'default' => 0, + 'type' => 'bool' + }, + 'successLoginNumber' => { + 'default' => 5, + 'type' => 'int' + }, + 'sympaMailKey' => { + 'type' => 'text' + }, + 'sympaSecret' => { + 'type' => 'text' + }, + 'syslog' => { + 'default' => '', + 'msgFail' => + '__authorizedValues__: auth, authpriv, daemon, local0-7, user', + 'test' => qr/^(?:auth|authpriv|daemon|local\d|user)?$/, + 'type' => 'text' + }, + 'timeout' => { + 'default' => 72000, + 'type' => 'int' + }, + 'timeoutActivity' => { + 'default' => 0, + 'type' => 'select' + }, + 'trustedDomains' => { + 'type' => 'text' + }, + 'trustedProxies' => { + 'default' => '', + 'type' => 'text' + }, + 'twitterAppName' => { + 'type' => 'text' + }, + 'twitterAuthnLevel' => { + 'default' => 1, + 'type' => 'int' + }, + 'twitterKey' => { + 'type' => 'text' + }, + 'twitterSecret' => { + 'type' => 'text' + }, + 'userControl' => { + 'default' => '^[\\w\\.\\-@]+$', + 'type' => 'text' + }, + 'userDB' => { + 'default' => 'Demo', + 'type' => 'select' + }, + 'useRedirectOnError' => { + 'default' => 1, + 'type' => 'bool' + }, + 'useRedirectOnForbidden' => { + 'default' => 0, + 'type' => 'bool' + }, + 'userPivot' => { + 'type' => 'text' + }, + 'useSafeJail' => { + 'default' => 1, + 'type' => 'bool' + }, + 'vhostAliases' => { + 'type' => 'text' + }, + 'vhostHttps' => { + 'default' => -1, + 'type' => 'trool' + }, + 'vhostMaintenance' => { + 'default' => 0, + 'type' => 'bool' + }, + 'vhostOptions' => { + 'type' => 'subContainer' + }, + 'vhostPort' => { + 'default' => -1, + 'type' => 'int' + }, + 'virtualHosts' => { + 'type' => 'virtualHostContainer' + }, + 'webIDAuthnLevel' => { + 'default' => 1, + 'type' => 'int' + }, + 'webIDExportedVars' => { + 'default' => {}, + 'keyTest' => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + 'msgFail' => '__badValue__', + 'test' => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + 'type' => 'keyTextContainer' + }, + 'webIDWhitelist' => { + 'type' => 'text' + }, + 'whatToTrace' => { + 'default' => 'uid', + 'type' => 'text' + }, + 'yubikeyAuthnLevel' => { + 'default' => 3, + 'type' => 'int' + }, + 'yubikeyClientID' => { + 'type' => 'text' + }, + 'yubikeyPublicIDSize' => { + 'default' => 12, + 'type' => 'int' + }, + 'yubikeySecretKey' => { + 'type' => 'text' + }, + 'zimbraAccountKey' => { + 'type' => 'text' + }, + 'zimbraBy' => { + 'default' => '', + 'type' => 'select' + }, + 'zimbraPreAuthKey' => { + 'type' => 'text' + }, + 'zimbraSsoUrl' => { + 'type' => 'text' + }, + 'zimbraUrl' => { + 'type' => 'text' + } }; } -1; diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm new file mode 100644 index 000000000..a9387ea8e --- /dev/null +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm @@ -0,0 +1,2151 @@ +# This file contains the description of all configuration parameters +# It may be included only by batch files, never in portal or handler chain +# for performances reasons + +# DON'T FORGET TO RUN jsongenerator.pl AFTER EACH CHANGE + +package Lemonldap::NG::Manager::Build::Attributes; + +our $VERSION = '1.9.0'; +use strict; +use Regexp::Common qw/URI/; + +my $perlExpr = sub { + my $s = eval { $_[0] }; + return $@ ? ( 0, "__badExpression__: $@" ) : (1); +}; + +sub types { + return { + + # Simple text types + text => { + test => qr/.*/, + msgFail => '__malformedValue__', + }, + password => { + test => qr/.*/, + msgFail => '__malformedValue__', + }, + longtext => { + test => sub { 1 } + }, + url => { + form => 'text', + test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, + msgFail => '__badUrl__', + }, + PerlModule => { + form => 'text', + test => qr/^[a-zA-Z][a-zA-Z0-9]*(?:::[a-zA-Z][a-zA-Z0-9]*)*$/, + msgFail => '__badPerlPackageName__', + }, + hostname => { + form => 'text', + test => qr/^(?:$Regexp::Common::URI::RFC2396::host)?$/, + msgFail => '__badHostname__', + }, + pcre => { + form => 'text', + test => sub { + eval { qr/$_[0]/ }; + return $@ ? ( 0, "__badRegexp__: $@" ) : (1); + }, + }, + lmAttrOrMacro => { + form => 'text', + test => sub { 1 }, + }, + + # Other types + int => { + test => qr/^\-?\d+$/, + msgFail => '__notAnInteger__', + }, + bool => { + test => qr/^[01]$/, + msgFail => '__notABoolean__', + }, + trool => { + test => qr/^(?:-1|0|1)$/, + msgFail => '__authorizedValues__: -1, 0, 1', + }, + boolOrExpr => { + test => $perlExpr, + msgFail => '__notAValidPerlExpression__', + }, + + # Files type (long text) + file => { + test => sub { 1 } + }, + RSAPublicKey => { + test => +qr/^(?:\-+\s*BEGIN\s+PUBLIC\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+PUBLIC\s+KEY\s*\-+)?[\r\n]*$/s, + msgFail => '__badPemEncoding__', + }, + RSAPrivateKey => { + test => +qr/^(?:\-+\s*BEGIN\s+RSA\s+PRIVATE\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+RSA\s+PRIVATE\s+KEY\s*\-+)?[\r\n]*$/s, + msgFail => '__badPemEncoding__', + }, + + authParamsText => { + test => sub { 1 } + }, + blackWhiteList => { + test => sub { 1 } + }, + catAndAppList => { + test => sub { 1 } + }, + keyText => { + keyTest => qr/^[a-zA-Z0-9_]+$/, + test => qr/^.*$/, + msgFail => '__badValue__', + }, + menuApp => { + test => sub { 1 } + }, + menuCat => { + test => sub { 1 } + }, + oidcOPMetaDataNode => { + test => sub { 1 } + }, + oidcRPMetaDataNode => { + test => sub { 1 } + }, + oidcmetadatajson => { + test => sub { 1 } + }, + oidcmetadatajwks => { + test => sub { 1 } + }, + portalskin => { + test => sub { 1 } + }, + portalskinbackground => { + test => sub { 1 } + }, + post => { + test => sub { 1 } + }, + rule => { + test => sub { 1 } + }, + samlAssertion => { + test => sub { 1 } + }, + samlAttribute => { + test => sub { 1 } + }, + samlIDPMetaDataNode => { + test => sub { 1 } + }, + samlSPMetaDataNode => { + test => sub { 1 } + }, + samlService => { + test => sub { 1 } + }, + select => { + test => sub { + my $test = + grep { $_ eq $_[0] } map { $_->{k} } @{ $_[2]->{select} }; + return $test ? 1 : 0; + }, + }, + virtualHost => { + test => sub { 1 } + }, + + }; +} + +sub attributes { + return { + + # Other + cfgNum => { + type => 'int', + default => 0, + documentation => 'Enable Cross Domain Authentication', + }, + cfgAuthor => { + type => 'text', + documentation => 'Name of the author of the current configuration', + }, + cfgAuthorIP => { + type => 'text', + documentation => 'Uploader IP address of the current configuration', + }, + cfgDate => { + type => 'int', + documentation => 'Timestamp of the current configuration', + }, + cfgLog => { + type => 'longtext', + documentation => 'Configuration update log', + }, + confirmFormMethod => { + type => "select", + select => + [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ], + default => 'post', + documentation => 'HTTP method for confirm page form', + }, + customFunctions => { type => 'text', }, + https => { + default => 0, + type => 'bool', + documentation => 'Use HTTPS for redirection from portal', + }, + infoFormMethod => { + type => "select", + select => + [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ], + default => 'get', + documentation => 'HTTP method for info page form', + }, + port => { type => 'int', }, + jsRedirect => { + type => 'boolOrExpr', + default => 0, + documentation => 'Use javascript for redirections', + }, + logoutServices => { + type => 'keyTextContainer', + help => 'logoutforward.html', + default => {}, + documentation => 'Send logout trough GET request to these services', + }, + maintenance => { + default => 0, + type => 'bool', + documentation => 'Maintenance mode for all virtual hosts', + }, + portal => { + type => 'url', + default => 'http://auth.example.com/', + documentation => 'Portal URL', + }, + portalUserAttr => { + type => 'text', + default => '_user', + documentation => + 'Session parameter to display connected user in portal', + }, + redirectFormMethod => { + type => "select", + select => + [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ], + default => 'get', + documentation => 'HTTP method for redirect page form', + }, + reloadUrls => { + type => 'keyTextContainer', + help => 'configlocation.html#configuration_reload', + keyTest => qr/^$Regexp::Common::URI::RFC2396::host$/, + test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, + msgFail => '__badUrl__' + }, + staticPrefix => { + type => 'text', + documentation => 'Prefix of static files for HTML templates', + }, + syslog => { + type => 'text', + test => qr/^(?:auth|authpriv|daemon|local\d|user)?$/, + msgFail => + '__authorizedValues__: auth, authpriv, daemon, local0-7, user', + default => '', + documentation => 'Syslog facility', + }, + + # Manager + protection => { + type => 'text', + test => qr/^(?:none|authenticate|manager|)$/, + msgFail => '__authorizedValues__: none authenticate manager', + default => 'none', + documentation => 'Manager protection method', + }, + + # Menu + activeTimer => { + default => 0, + type => 'bool', + default => 1, + documentation => 'Enable timers on portal pages', + }, + applicationList => { + type => 'catAndAppList', + help => 'portalmenu.html#categories_and_applications', + default => { + default => { catname => 'Default category', type => "category" } + }, + documentation => 'Applications list', + }, + portalOpenLinkInNewWindow => { + type => 'bool', + default => 0, + documentation => 'Open applications in new windows', + }, + portalPingInterval => { + type => 'int', + default => 60000, + documentation => 'Interval in ms between portal Ajax pings ', + }, + portalSkin => { + type => 'portalskin', + default => 'bootstrap', + documentation => 'Name of portal skin', + select => [ + { k => 'bootstrap', v => 'Bootstrap' }, + { k => 'pastel', v => 'Pastel' }, + { k => 'impact', v => 'Impact' }, + { k => 'dark', v => 'Dark' }, + ], + }, + portalSkinBackground => { + type => 'portalskinbackground', + documentation => 'Background image of portal skin', + select => [ + { k => "", v => 'None' }, + { + k => "1280px-Anse_Source_d'Argent_2-La_Digue.jpg", + v => 'Anse' + }, + { + k => +"1280px-Autumn-clear-water-waterfall-landscape_-_Virginia_-_ForestWander.jpg", + v => 'Waterfall' + }, + { k => "1280px-BrockenSnowedTrees.jpg", v => 'Snowed Trees' }, + { + k => "1280px-Cedar_Breaks_National_Monument_partially.jpg", + v => 'National Monument' + }, + { + k => "1280px-Parry_Peak_from_Winter_Park.jpg", + v => 'Winter' + }, + { k => "Aletschgletscher_mit_Pinus_cembra1.jpg", v => 'Pinus' }, + ], + }, + portalSkinRules => { + type => 'keyTextContainer', + help => 'portalcustom.html', + keyTest => $perlExpr, + keyMsgFail => 'Bad skin rule', + test => qr/^\w+$/, + msgFail => '__badValue__', + }, + + # Security + cda => { + default => 0, + type => 'bool', + documentation => 'Enable Cross Domain Authentication', + }, + checkXSS => { + default => 1, + type => 'bool', + documentation => 'Check XSS', + }, + grantSessionRules => { + type => 'keyTextContainer', + keyTest => $perlExpr, + }, + hiddenAttributes => { + type => 'text', + default => '_password', + documentation => 'Name of attributes to hide in logs', + }, + key => { + type => 'password', + documentation => 'Secret key', + }, + portalAntiFrame => { + default => 1, + type => 'bool', + documentation => 'Avoid portal to be displayed inside frames', + }, + portalCheckLogins => { + default => 1, + type => 'bool', + default => 1, + documentation => 'Display login history checkbox in portal', + }, + portalForceAuthn => { + default => 0, + type => 'bool', + documentation => 'Force to authenticate when displaying portal', + }, + portalForceAuthnInterval => { + type => 'int', + default => 0, + documentation => +'Minimum number of seconds since last authentifcation to force reauthentication', + }, + randomPasswordRegexp => { + type => 'pcre', + default => '[A-Z]{3}[a-z]{5}.\d{2}', + documentation => 'Regular expression to create a random password', + }, + trustedDomains => { type => 'text', }, + storePassword => { + default => 0, + type => 'bool', + documentation => 'Store password in session', + }, + timeout => { + type => 'int', + default => 72000, + documentation => 'Session timeout on server side', + }, + timeoutActivity => { + select => [ + { k => '0', v => 'None' }, + { k => '900', v => '15 min' }, + { k => '1800', v => '30 min' }, + { k => '2700', v => '45 min' }, + { k => '3600', v => '60 min' }, + ], + type => 'select', + default => 0, + documentation => 'Session activity timeout on server side', + }, + trustedProxies => { + type => 'text', + default => '', + documentation => 'Trusted proxies', + }, + userControl => { + type => 'pcre', + default => '^[\w\.\-@]+$', + documentation => 'Regular expression to validate login', + }, + useRedirectOnError => { + type => 'bool', + default => 1, + documentation => 'Use 302 redirect code for error (500)', + }, + useRedirectOnForbidden => { + default => 0, + type => 'bool', + documentation => 'Use 302 redirect code for forbidden (403)', + }, + useSafeJail => { + default => 1, + type => 'bool', + documentation => 'Activate Safe jail', + }, + whatToTrace => { + type => 'lmAttrOrMacro', + default => 'uid', + documentation => 'Session parameter used to fill REMOTE_USER', + }, + + # History + failedLoginNumber => { + default => 5, + type => 'int', + documentation => 'Number of failures stored in login history', + }, + loginHistoryEnabled => { + default => 0, + type => 'bool', + default => 1, + documentation => 'Enable login history', + }, + portalDisplayLoginHistory => { + type => 'boolOrExpr', + default => 1, + documentation => 'Display login history tab in portal', + }, + successLoginNumber => { + default => 5, + type => 'int', + documentation => 'Number of success stored in login history', + }, + + # Other displays + portalDisplayAppslist => { + type => 'boolOrExpr', + default => 1, + documentation => 'Display applications tab in portal', + }, + portalDisplayChangePassword => { + type => 'boolOrExpr', + default => '$_auth =~ /^(LDAP|DBI|Demo)$/', + documentation => 'Display password tab in portal', + }, + portalDisplayLogout => { + default => 1, + type => 'boolOrExpr', + documentation => 'Display logout tab in portal', + }, + portalDisplayRegister => { + default => 1, + type => 'bool', + documentation => 'Display register button in portal', + }, + portalDisplayResetPassword => { + default => 1, + type => 'bool', + documentation => 'Display reset password button in portal', + }, + + # Cookies + cookieExpiration => { type => 'text', }, + cookieName => { + type => 'text', + test => qr/^[a-zA-Z][a-zA-Z0-9_-]*$/, + msgFail => '__badCookieName__', + default => 'lemonldap', + documentation => 'Name of the main cookie', + }, + domain => { + type => 'text', + test => qr/^(?:$Regexp::Common::URI::RFC2396::hostname)?/, + msgFail => '__badDomainName__', + default => 'example.com', + documentation => 'DNS domain', + }, + httpOnly => { + default => 1, + type => 'bool', + documentation => 'Enable httpOnly flag in cookie', + }, + securedCookie => { + type => 'select', + select => [ + { k => '0', v => 'unsecuredCookie' }, + { k => '1', v => 'securedCookie' }, + { k => '2', v => 'doubleCookie' }, + { k => '3', v => 'doubleCookieForSingleSession' }, + ], + default => 0, + documentation => 'Cookie securisation method', + }, + + # Notification + notificationStorage => { type => 'PerlModule', }, + notificationWildcard => { + type => 'text', + default => 'allusers', + documentation => 'Notification string to match all users', + }, + notificationXSLTfile => { type => 'text', }, + notification => { + default => 0, + type => 'bool', + documentation => 'Notification activation', + }, + notificationStorage => { + type => 'PerlModule', + default => 'File', + documentation => 'Notification backend', + }, + notificationStorageOptions => { + type => 'keyTextContainer', + default => { dirName => '/var/lib/lemonldap-ng/notifications', }, + documentation => 'Notification backend options', + }, + + # Captcha + captcha_login_enabled => { + default => 0, + type => 'bool', + documentation => 'Captcha on login page', + }, + captcha_mail_enabled => { + default => 0, + type => 'bool', + documentation => 'Captcha on password reset page', + }, + captcha_register_enabled => { + default => 1, + type => 'bool', + documentation => 'Captcha on account creation page', + }, + captcha_size => { + type => 'int', + default => 6, + documentation => 'Captcha size', + }, + + #captcha_data => { + #captcha_output => { + captchaStorage => { + type => 'PerlModule', + default => 'Apache::Session::File', + documentation => 'Captcha backend module', + }, + captchaStorageOptions => { + type => 'keyTextContainer', + default => { 'Directory' => '/var/lib/lemonldap-ng/captcha/', }, + documentation => 'Captcha backend module options', + }, + + # Variables + exportedVars => { + type => 'keyTextContainer', + help => 'exportedvars.html', + keyTest => qr/^!?[_a-zA-Z][a-zA-Z0-9_]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[_a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => { 'UA' => 'HTTP_USER_AGENT' }, + documentation => 'Main exported variables', + }, + groups => { + type => 'keyTextContainer', + help => + 'exportedvars.html#extend_variables_using_macros_and_groups', + test => $perlExpr, + default => {}, + documentation => 'Groups', + }, + macros => { + type => 'keyTextContainer', + help => + 'exportedvars.html#extend_variables_using_macros_and_groups', + keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/, + keyMsgFail => 'Bad macro name', + test => $perlExpr, + default => {}, + documentation => 'Macros', + }, + + # Storage + globalStorage => { + type => 'PerlModule', + default => 'Apache::Session::File', + documentation => 'Session backend module', + }, + globalStorageOptions => { + type => 'keyTextContainer', + default => { + 'Directory' => '/var/lib/lemonldap-ng/sessions/', + 'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/', + 'generateModule' => + 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', + }, + documentation => 'Session backend module options', + }, + localSessionStorage => { + type => 'PerlModule', + default => 'Cache::FileCache', + , documentation => 'Sessions cache module', + }, + localSessionStorageOptions => { + type => 'keyTextContainer', + default => { + 'namespace' => 'lemonldap-ng-sessions', + 'default_expires_in' => 600, + 'directory_umask' => '007', + 'cache_root' => '/tmp', + 'cache_depth' => 3, + }, + documentation => 'Sessions cache module options', + }, + + # Persistent storage + persistentStorage => { type => 'PerlModule', }, + persistentStorageOptions => { type => 'keyTextContainer', }, + sessionDataToRemember => { + type => 'keyTextContainer', + keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/, + keyMsgFail => 'Invalid session data', + }, + + # SAML issuer + issuerDBSAMLActivation => { + default => 0, + type => 'bool', + documentation => 'SAML IDP activation', + }, + issuerDBSAMLPath => { + type => 'pcre', + default => '^/saml/', + documentation => 'SAML IDP request path', + }, + issuerDBSAMLRule => { + type => 'boolOrExpr', + default => 1, + documentation => 'SAML IDP rule', + }, + + # OpenID-Connect issuer + issuerDBOpenIDConnectActivation => { + type => 'bool', + default => '0', + documentation => 'OpenID Connect server activation', + }, + issuerDBOpenIDConnectPath => { + type => 'text', + default => '^/oauth2/', + documentation => 'OpenID Connect server request path', + }, + issuerDBOpenIDConnectRule => { + type => 'boolOrExpr', + default => 1, + documentation => 'OpenID Connect server rule', + }, + + # Password + mailOnPasswordChange => { + default => 0, + type => 'bool', + documentation => 'Send a mail when password is changed', + }, + portalRequireOldPassword => { + default => 1, + type => 'bool', + documentation => 'Old password is required to change the password', + }, + hideOldPassword => { + default => 0, + type => 'bool', + documentation => 'Hide old password in portal', + }, + + # Mails + mailBody => { type => 'longtext', }, + mailCharset => { + type => 'text', + default => 'utf-8', + documentation => 'Mail charset', + }, + mailConfirmBody => { type => 'longtext', }, + mailConfirmSubject => { + type => 'text', + default => '[LemonLDAP::NG] Password reset confirmation', + documentation => 'Mail subject for reset confirmation', + }, + mailFrom => { + type => 'text', + default => 'noreply@example.com', + documentation => 'Sender email', + }, + mailReplyTo => { type => 'text', }, + mailSessionKey => { + type => 'text', + default => 'mail', + documentation => 'Session parameter where mail is stored', + }, + mailSubject => { + type => 'text', + default => '[LemonLDAP::NG] Your new password', + documentation => 'Mail subject for new password email', + }, + mailTimeout => { + type => 'int', + default => 0, + documentation => 'Mail session timeout', + }, + mailUrl => { + type => 'url', + default => 'http://auth.example.com/mail.pl', + documentation => 'URL of password reset page', + }, + SMTPServer => { + type => 'hostname', + default => '', + documentation => 'SMTP Server', + }, + SMTPAuthUser => { type => 'text', }, + SMTPAuthPass => { type => 'password', }, + + # Registration + registerConfirmSubject => { + type => 'text', + default => '[LemonLDAP::NG] Account register confirmation', + documentation => 'Mail subject for register confirmation', + }, + registerDB => { + type => 'select', + select => [ + { k => 'AD', v => 'Active Directory' }, + { k => 'Demo', v => 'Demonstration' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Null', v => 'None' }, + ], + default => 'Demo', + documentation => 'Register module', + }, + registerDoneSubject => { + type => 'text', + default => '[LemonLDAP::NG] Your new account', + documentation => 'Mail subject when register is done', + }, + registerTimeout => { + default => 0, + type => 'int', + documentation => 'Register session timeout', + }, + registerUrl => { + type => 'text', + default => 'http://auth.example.com/register.pl', + documentation => 'URL of register page', + }, + + # Single session + notifyDeleted => { + default => 1, + type => 'bool', + documentation => 'Show deleted sessions in portal', + }, + notifyOther => { + default => 0, + type => 'bool', + documentation => 'Show other sessions in portal', + }, + singleSession => { + default => 0, + type => 'bool', + documentation => 'Allow only one session per user', + }, + singleIP => { + default => 0, + type => 'bool', + documentation => 'Allow only one session per IP', + }, + singleUserByIP => { + default => 0, + type => 'bool', + }, + singleSessionUserByIP => { + default => 0, + type => 'bool', + documentation => 'Allow only one session per user on an IP', + }, + + # SOAP server + Soap => { + default => 0, + type => 'bool', + documentation => 'Enable SOAP services', + }, + exportedAttr => { type => 'text', }, + + ## Virtualhosts + + # Fake attribute: used by manager REST API to agglomerate all other + # nodes + virtualHosts => { + type => 'virtualHostContainer', + help => 'configvhost.html', + template => 'virtualHost', + }, + + locationRules => { + type => 'ruleContainer', + help => 'writingrulesand_headers.html#rules', + keyTest => $Regexp::Common::URI::RFC2396::hostname, + msgFail => '__badHostname__', + default => { + default => 'deny', + }, + documentation => 'Virtualhost rules', + }, + exportedHeaders => { + type => 'keyTextContainer', + help => 'writingrulesand_headers.html#headers', + keyTest => $Regexp::Common::URI::RFC2396::hostname, + keyMsgFail => '__badHostname__', + documentation => 'Virtualhost headers', + }, + post => { + type => 'postContainer', + help => 'formreplay.html', + keyTest => $Regexp::Common::URI::RFC2396::hostname, + keyMsgFail => '__badHostname__', + documentation => 'Virtualhost urls/Datas to post', + }, + + vhostOptions => { + type => 'subContainer', + }, + vhostPort => { + type => 'int', + default => -1, + }, + vhostHttps => { + type => 'trool', + default => -1, + }, + vhostMaintenance => { + type => 'bool', + default => 0, + }, + vhostAliases => { + type => 'text', + }, + + # CAS IDP + casAttr => { type => 'text', }, + casAttributes => { type => 'keyTextContainer', }, + casAccessControlPolicy => { + type => 'select', + select => [ + { k => 'none', v => 'None' }, + { k => 'error', v => 'Display error on portal' }, + { k => 'faketicket', v => 'Send a fake service ticket' }, + ], + default => 'none', + documentation => 'CAS access control policy', + }, + casStorage => { type => 'PerlModule', }, + casStorageOptions => { + type => 'keyTextContainer', + }, + issuerDBCASActivation => { + default => 0, + type => 'bool', + documentation => 'CAS server activation', + }, + issuerDBCASPath => { + type => 'pcre', + default => '^/cas/', + documentation => 'CAS server request path', + }, + issuerDBCASRule => { + type => 'boolOrExpr', + default => 1, + documentation => 'CAS server rule', + }, + + # OpenID Issuer + issuerDBOpenIDActivation => { + default => 0, + type => 'bool', + documentation => 'OpenID server activation', + }, + issuerDBOpenIDPath => { + type => 'pcre', + default => '^/openidserver/', + documentation => 'OpenID server request path', + }, + issuerDBOpenIDRule => { + type => 'boolOrExpr', + default => 1, + documentation => 'OpenID server rule', + }, + + openIdIssuerSecret => { type => 'text', }, + openIdAttr => { type => 'text', }, + openIdSreg_fullname => { + type => 'lmAttrOrMacro', + default => 'cn', + documentation => 'OpenID SREG fullname session parameter', + }, + openIdSreg_nickname => { + type => 'lmAttrOrMacro', + default => 'uid', + documentation => 'OpenID SREG nickname session parameter', + }, + openIdSreg_language => { type => 'lmAttrOrMacro', }, + openIdSreg_postcode => { type => 'lmAttrOrMacro', }, + openIdSreg_timezone => { + type => 'lmAttrOrMacro', + default => '_timezone', + documentation => 'OpenID SREG timezone session parameter', + }, + openIdSreg_country => { type => 'lmAttrOrMacro', }, + openIdSreg_gender => { type => 'lmAttrOrMacro', }, + openIdSreg_email => { + type => 'lmAttrOrMacro', + default => 'mail', + documentation => 'OpenID SREG email session parameter', + }, + openIdSreg_dob => { type => 'lmAttrOrMacro', }, + openIdSPList => { type => 'blackWhiteList', default => '0;' }, + + # Zimbra + zimbraPreAuthKey => { type => 'text', }, + zimbraAccountKey => { type => 'text', }, + zimbraBy => { + type => 'select', + select => [ + { k => '', v => '' }, + { k => 'name', v => 'User name' }, + { k => 'id', v => 'User id' }, + { k => 'foreignPrincipal', v => 'Foreign principal' }, + ], + default => '', + }, + zimbraUrl => { type => 'url', }, + zimbraSsoUrl => { type => 'url', }, + + # Sympa + sympaSecret => { type => 'text', }, + sympaMailKey => { type => 'text', }, + + # Secure Token + secureTokenMemcachedServers => { + type => 'text', + default => '127.0.0.1:11211', + documentation => 'Secure Token Handler memcached servers', + }, + secureTokenExpiration => { + type => 'int', + default => 60, + documentation => 'Secure Token Handler token expiration', + }, + secureTokenAttribute => { + type => 'text', + default => 'uid', + documentation => 'Secure Token Handler attribute to store', + }, + secureTokenUrls => { + type => 'pcre', + default => '.*', + documentation => + 'Secure Token Handler regular expression to match protected URL', + }, + secureTokenHeader => { + type => 'text', + default => 'Auth-Token', + documentation => 'Secure Token Handler header name', + }, + secureTokenAllowOnError => { + default => 1, + type => 'bool', + documentation => 'Secure Token Handler allow request on error', + }, + ######### + ## SAML # + ######### + samlEntityID => { + type => 'text', + default => '#PORTAL#/saml/metadata', + documentation => 'SAML service entityID', + }, + samlOrganizationDisplayName => { + type => 'text', + default => 'Example', + documentation => 'SAML service organization display name', + }, + samlOrganizationName => { + type => 'text', + default => 'Example', + documentation => 'SAML service organization name', + }, + samlOrganizationURL => { + type => 'text', + default => 'http://www.example.com', + documentation => 'SAML service organization URL', + }, + samlNameIDFormatMapEmail => { + type => 'text', + default => 'mail', + documentation => 'SAML session parameter for NameID email', + }, + samlNameIDFormatMapX509 => { + type => 'text', + default => 'mail', + documentation => 'SAML session parameter for NameID x509', + }, + samlNameIDFormatMapWindows => { + type => 'text', + default => 'uid', + documentation => 'SAML session parameter for NameID windows', + }, + samlNameIDFormatMapKerberos => { + type => 'text', + default => 'uid', + documentation => 'SAML session parameter for NameID kerberos', + }, + samlAttributeAuthorityDescriptorAttributeServiceSOAP => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' + . '#PORTAL#/saml/AA/SOAP;', + documentation => 'SAML Attribute Authority SOAP', + }, + samlServicePrivateKeySig => { + type => 'RSAPrivateKey', + default => '', + documentation => 'SAML signature private key', + }, + samlServicePrivateKeySigPwd => { + type => 'password', + default => '', + documentation => 'SAML signature private key password', + }, + samlServicePublicKeySig => { + type => 'RSAPublicKey', + default => '', + documentation => 'SAML signature public key', + }, + samlServicePrivateKeyEnc => { + type => 'RSAPrivateKey', + default => '', + documentation => 'SAML encryption private key', + }, + samlServicePrivateKeyEncPwd => { type => 'password', }, + samlServicePublicKeyEnc => { + type => 'RSAPublicKey', + default => '', + documentation => 'SAML encryption public key', + }, + samlIdPResolveCookie => { + type => 'text', + default => 'lemonldapidp', + documentation => 'SAML IDP resolution cookie', + }, + samlMetadataForceUTF8 => { + default => 1, + type => 'bool', + documentation => 'SAML force metadata UTF8 conversion', + }, + samlStorage => { type => 'PerlModule', }, + samlStorageOptions => { type => 'keyTextContainer', }, + samlAuthnContextMapPassword => { + type => 'int', + default => 2, + documentation => 'SAML authn context password level', + }, + samlAuthnContextMapPasswordProtectedTransport => { + type => 'int', + default => 3, + documentation => + 'SAML authn context password protected transport level', + }, + samlAuthnContextMapTLSClient => { + type => 'int', + default => 5, + documentation => 'SAML authn context TLS client level', + }, + samlAuthnContextMapKerberos => { + type => 'int', + default => 4, + documentation => 'SAML authn context kerberos level', + }, + samlCommonDomainCookieActivation => { + default => 0, + type => 'bool', + documentation => 'SAML CDC activation', + }, + samlCommonDomainCookieDomain => { + type => 'text', + test => qr/^$Regexp::Common::URI::RFC2396::hostname$/, + msgFail => '__badDomainName__', + }, + samlCommonDomainCookieReader => { + type => 'text', + test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, + msgFail => '__badUrl__', + }, + samlCommonDomainCookieWriter => { + type => 'text', + test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, + msgFail => '__badUrl__', + }, + samlRelayStateTimeout => { + type => 'int', + default => 600, + documentation => 'SAML timeout of relay state', + }, + samlUseQueryStringSpecific => { + default => 0, + type => 'bool', + documentation => 'SAML use specific method for query_string', + }, + samlIDPSSODescriptorWantAuthnRequestsSigned => { + type => 'bool', + default => 1, + documentation => 'SAML IDP want authn request signed', + }, + samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;' + . '#PORTAL#/saml/singleSignOn;', + documentation => 'SAML IDP SSO HTTP Redirect', + }, + samlIDPSSODescriptorSingleSignOnServiceHTTPPost => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' + . '#PORTAL#/saml/singleSignOn;', + documentation => 'SAML IDP SSO HTTP POST', + }, + samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;' + . '#PORTAL#/saml/singleSignOnArtifact;', + documentation => 'SAML IDP SSO HTTP Artifact', + }, + samlIDPSSODescriptorSingleSignOnServiceSOAP => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' + . '#PORTAL#/saml/singleSignOnSOAP;', + documentation => 'SAML IDP SSO SOAP', + }, + samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;' + . '#PORTAL#/saml/singleLogout;' + . '#PORTAL#/saml/singleLogoutReturn', + documentation => 'SAML IDP SLO HTTP Redirect', + }, + samlIDPSSODescriptorSingleLogoutServiceHTTPPost => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' + . '#PORTAL#/saml/singleLogout;' + . '#PORTAL#/saml/singleLogoutReturn', + documentation => 'SAML IDP SLO HTTP POST', + }, + samlIDPSSODescriptorSingleLogoutServiceSOAP => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' + . '#PORTAL#/saml/singleLogoutSOAP;', + documentation => 'SAML IDP SLO SOAP', + }, + samlIDPSSODescriptorArtifactResolutionServiceArtifact => { + type => 'samlAssertion', + default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' + . '#PORTAL#/saml/artifact', + documentation => 'SAML IDP artifact resolution service', + }, + + # Fake attribute: used by manager REST API to agglomerate all nodes + # related to a SAML IDP partner + samlIDPMetaDataNodes => { + type => 'samlIDPMetaDataNodeContainer', + template => 'samlIDPMetaDataNode', + }, + + # Fake attribute: used by manager REST API to agglomerate all nodes + # related to a SAML SP partner + samlSPMetaDataNodes => { + type => 'samlSPMetaDataNodeContainer', + template => 'samlSPMetaDataNode', + }, + + # TODO: split that + # IDP Keys + samlIDPMetaDataExportedAttributes => { + type => 'samlAttributeContainer', + help => 'authsaml.html#exported_attributes', + keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + keyMsgFail => 'Bad metadata name', + default => ';;;', + }, + samlIDPMetaDataXML => { + type => 'file', + }, + samlIDPMetaDataOptions => { + type => 'keyTextContainer', + keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + keyMsgFail => 'Bad metadata name', + }, + samlIDPMetaDataOptionsNameIDFormat => { + type => 'select', + select => [ + { k => '', v => '' }, + { k => 'unspecified', v => 'Unspecified' }, + { k => 'email', v => 'Email' }, + { k => 'x509', v => 'X509 certificate' }, + { k => 'windows', v => 'Windows' }, + { k => 'kerberos', v => 'Kerberos' }, + { k => 'entity', v => 'Entity' }, + { k => 'persistent', v => 'Persistent' }, + { k => 'transient', v => 'Transient' }, + { k => 'encrypted', v => 'Encrypted' }, + ], + default => '', + }, + samlIDPMetaDataOptionsForceAuthn => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsIsPassive => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsAllowProxiedAuthn => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsAllowLoginFromIDP => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsRequestedAuthnContext => { + type => 'select', + select => [ + { k => '', v => '' }, + { k => 'kerberos', v => 'Kerberos' }, + { + k => 'password-protected-transport', + v => 'Password protected transport' + }, + { k => 'password', v => 'Password' }, + { k => 'tls-client', v => 'TLS client certificate' }, + ], + default => '', + }, + samlIDPMetaDataOptionsAdaptSessionUtime => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsForceUTF8 => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsSignSSOMessage => { + type => 'trool', + default => -1, + }, + samlIDPMetaDataOptionsCheckSSOMessageSignature => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsSignSLOMessage => { + type => 'trool', + default => -1, + }, + samlIDPMetaDataOptionsCheckSLOMessageSignature => { + type => 'bool', + default => 0, + }, + samlIDPMetaDataOptionsSSOBinding => { + type => 'select', + select => [ + { k => '', v => '' }, + { k => 'http-post', v => 'POST' }, + { k => 'http-redirect', v => 'Redirect' }, + { k => 'http-soap', v => 'SOAP' }, + { k => 'artifact-get', v => 'Artifact GET' }, + { k => 'artifact-post', v => 'Artifact POST' }, + ], + default => '', + }, + samlIDPMetaDataOptionsSLOBinding => { + type => 'text', + }, + samlIDPMetaDataOptionsEncryptionMode => { + type => 'select', + select => [ + { k => 'none', v => 'None' }, + { k => 'nameid', v => 'Name ID' }, + { k => 'assertion', v => 'Assertion' }, + ], + default => 'none', + }, + samlIDPMetaDataOptionsCheckConditions => { + type => 'bool', + default => 0, + }, + + # SP keys + samlSPMetaDataExportedAttributes => { + type => 'samlAttributeContainer', + help => 'idpsaml.html#exported_attributes', + keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + keyMsgFail => 'Bad metadata name', + default => ';;;', + }, + samlSPMetaDataXML => { + type => 'file', + }, + samlSPMetaDataOptions => { + type => 'keyTextContainer', + keyTest => qr/^[a-zA-Z](?:[a-zA-Z0-9_\-\.]*\w)?$/, + keyMsgFail => 'Bad metadata name', + }, + samlSPSSODescriptorAuthnRequestsSigned => { + default => 1, + type => 'bool', + documentation => 'SAML SP AuthnRequestsSigned', + }, + samlSPSSODescriptorWantAssertionsSigned => { + default => 1, + type => 'bool', + documentation => 'SAML SP WantAssertionsSigned', + }, + samlSPSSODescriptorSingleLogoutServiceHTTPRedirect => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;' + . '#PORTAL#/saml/proxySingleLogout;' + . '#PORTAL#/saml/proxySingleLogoutReturn', + documentation => 'SAML SP SLO HTTP Redirect', + }, + samlSPSSODescriptorSingleLogoutServiceHTTPPost => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' + . '#PORTAL#/saml/proxySingleLogout;' + . '#PORTAL#/saml/proxySingleLogoutReturn', + documentation => 'SAML SP SLO HTTP POST', + }, + samlSPSSODescriptorSingleLogoutServiceSOAP => { + type => 'samlService', + default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' + . '#PORTAL#/saml/proxySingleLogoutSOAP;', + documentation => 'SAML SP SLO SOAP', + }, + samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => { + type => 'samlAssertion', + default => + '1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;' + . '#PORTAL#/saml/proxySingleSignOnArtifact', + documentation => 'SAML SP ACS HTTP artifact', + }, + samlSPSSODescriptorAssertionConsumerServiceHTTPPost => { + type => 'samlAssertion', + default => '0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;' + . '#PORTAL#/saml/proxySingleSignOnPost', + documentation => 'SAML SP ACS HTTP POST', + }, + samlSPSSODescriptorArtifactResolutionServiceArtifact => { + type => 'samlAssertion', + default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;' + . '#PORTAL#/saml/artifact', + documentation => 'SAML SP artifact resolution service ', + }, + samlSPMetaDataOptionsNameIDFormat => { + type => 'select', + select => [ + { k => '', v => '' }, + { k => 'unspecified', v => 'Unspecified' }, + { k => 'email', v => 'Email' }, + { k => 'x509', v => 'X509 certificate' }, + { k => 'windows', v => 'Windows' }, + { k => 'kerberos', v => 'Kerberos' }, + { k => 'entity', v => 'Entity' }, + { k => 'persistent', v => 'Persistent' }, + { k => 'transient', v => 'Transient' }, + { k => 'encrypted', v => 'Encrypted' }, + ], + default => '', + }, + samlSPMetaDataOptionsNameIDSessionKey => { + type => 'text', + }, + samlSPMetaDataOptionsOneTimeUse => { + type => 'bool', + default => 0, + }, + samlSPMetaDataOptionsSessionNotOnOrAfterTimeout => { + type => 'int', + default => 72000, + }, + samlSPMetaDataOptionsNotOnOrAfterTimeout => { + type => 'int', + default => 72000, + }, + samlSPMetaDataOptionsSignSSOMessage => { + type => 'trool', + default => -1, + }, + samlSPMetaDataOptionsCheckSSOMessageSignature => { + type => 'bool', + default => 0, + }, + samlSPMetaDataOptionsSignSLOMessage => { + type => 'trool', + default => -1, + }, + samlSPMetaDataOptionsCheckSLOMessageSignature => { + type => 'bool', + default => 0, + }, + samlSPMetaDataOptionsEncryptionMode => { + type => 'select', + select => [ + { k => 'none', v => 'None' }, + { k => 'nameid', v => 'Name ID' }, + { k => 'assertion', v => 'Assertion' }, + ], + default => 'none', + }, + samlSPMetaDataOptionsEnableIDPInitiatedURL => { + type => 'bool', + default => 0, + }, + + # AUTH, USERDB and PASSWORD MODULES + authentication => { + type => 'select', + select => [ + { k => 'Apache', v => 'Apache' }, + { k => 'AD', v => 'Active Directory' }, + { k => 'BrowserID', v => 'BrowserID (Mozilla Persona)' }, + { k => 'Choice', v => 'authChoice' }, + { k => 'CAS', v => 'Central Authentication Service (CAS)' }, + { k => 'DBI', v => 'Database (DBI)' }, + { k => 'Demo', v => 'Demonstration' }, + { k => 'Facebook', v => 'Facebook' }, + { k => 'Google', v => 'Google' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Multi', v => 'Multiple' }, + { k => 'Null', v => 'None' }, + { k => 'OpenID', v => 'OpenID' }, + { k => 'OpenIDConnect', v => 'OpenID Connect' }, + { k => 'Proxy', v => 'Proxy' }, + { k => 'Radius', v => 'Radius' }, + { k => 'Remote', v => 'Remote' }, + { k => 'SAML', v => 'SAML v2' }, + { k => 'Slave', v => 'Slave' }, + { k => 'SSL', v => 'SSL' }, + { k => 'Twitter', v => 'Twitter' }, + { k => 'WebID', v => 'WebID' }, + { k => 'Yubikey', v => 'Yubikey' }, + ], + default => 'Demo', + documentation => 'Authentication module', + }, + userDB => { + type => 'select', + select => [ + { k => 'AD', v => 'Active Directory' }, + { k => 'DBI', v => 'Database (DBI)' }, + { k => 'Choice', v => 'authChoice' }, + { k => 'Demo', v => 'Demonstration' }, + { k => 'Facebook', v => 'Facebook' }, + { k => 'Google', v => 'Google' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Multi', v => 'Multiple' }, + { k => 'Null', v => 'None' }, + { k => 'OpenID', v => 'OpenID' }, + { k => 'OpenIDConnect', v => 'OpenID Connect' }, + { k => 'Proxy', v => 'Proxy' }, + { k => 'Remote', v => 'Remote' }, + { k => 'SAML', v => 'SAML v2' }, + { k => 'Slave', v => 'Slave' }, + { k => 'WebID', v => 'WebID' }, + ], + default => 'Demo', + documentation => 'User module', + }, + passwordDB => { + type => 'select', + select => [ + { k => 'AD', v => 'Active Directory' }, + { k => 'Choice', v => 'authChoice' }, + { k => 'DBI', v => 'Database (DBI)' }, + { k => 'Demo', v => 'Demonstration' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Null', v => 'None' }, + ], + default => 'Demo', + documentation => 'Password module', + }, + + # DEMO + demoExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => { cn => 'cn', mail => 'mail', uid => 'uid', }, + documentation => 'Demo exported variables', + }, + + # AD + ADPwdExpireWarning => { + type => 'int', + default => 0, + documentation => 'AD password expire warning', + }, + ADPwdMaxAge => { + type => 'int', + default => 0, + documentation => 'AD password max age', + }, + + # LDAP + managerDn => { + type => 'text', + test => qr/^(?:\w+=.*)?$/, + msgFail => '__badValue__', + default => '', + documentation => 'LDAP manager DN', + }, + managerPassword => { + type => 'password', + test => qr/^\S*$/, + msgFail => '__badValue__', + default => '', + documentation => 'LDAP manager Password', + }, + ldapAuthnLevel => { + type => 'int', + default => 2, + documentation => 'LDAP authentication level', + }, + ldapBase => { + type => 'text', + test => qr/^(?:\w+=.*|)$/, + msgFail => '__badValue__', + default => 'dc=example,dc=com', + documentation => 'LDAP search base', + }, + ldapExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => { cn => 'cn', mail => 'mail', uid => 'uid', }, + documentation => 'LDAP exported variables', + }, + ldapPort => { + type => 'int', + default => 389, + documentation => 'LDAP port', + }, + ldapServer => { + type => 'text', + 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; + }, + default => 'ldap://localhost', + documentation => 'LDAP server (host or URI)', + }, + ldapPwdEnc => { + type => 'text', + test => qr/^[a-zA-Z0-9_][a-zA-Z0-9_\-]*[a-zA-Z0-9_]$/, + msgFail => '__badEncoding__', + default => 'utf-8', + documentation => 'LDAP password encoding', + }, + ldapUsePasswordResetAttribute => { + default => 0, + type => 'bool', + default => 1, + documentation => 'LDAP store reset flag in an attribute', + }, + ldapPasswordResetAttribute => { + type => 'text', + default => 'pwdReset', + documentation => 'LDAP password reset attribute', + }, + ldapPasswordResetAttributeValue => { + type => 'text', + default => 'TRUE', + documentation => 'LDAP password reset value', + }, + ldapPpolicyControl => { + default => 0, + type => 'bool', + }, + ldapSetPassword => { + default => 0, + type => 'bool', + }, + ldapChangePasswordAsUser => { + default => 0, + type => 'bool', + }, + mailLDAPFilter => { type => 'text', }, + LDAPFilter => { type => 'text', }, + AuthLDAPFilter => { type => 'text', }, + ldapGroupRecursive => { + default => 0, + type => 'bool', + documentation => 'LDAP recursive search in groups', + }, + ldapGroupObjectClass => { + type => 'text', + default => 'groupOfNames', + documentation => 'LDAP object class of groups', + }, + ldapGroupBase => { type => 'text', }, + ldapGroupAttributeName => { + type => 'text', + default => 'member', + documentation => 'LDAP attribute name for member in groups', + }, + ldapGroupAttributeNameUser => { + type => 'text', + default => 'dn', + documentation => +'LDAP attribute name in user entry referenced as member in groups', + }, + ldapGroupAttributeNameSearch => { + type => 'text', + default => 'cn', + documentation => 'LDAP attributes to search in groups', + }, + ldapGroupAttributeNameGroup => { + type => 'text', + default => 'dn', + documentation => +'LDAP attribute name in group entry referenced as member in groups', + }, + ldapTimeout => { + type => 'int', + default => 120, + documentation => 'LDAP connection timeout', + }, + ldapVersion => { + type => 'int', + default => 3, + documentation => 'LDAP protocol version', + }, + ldapRaw => { type => 'text', }, + + # SSL + SSLAuthnLevel => { + type => 'int', + default => 5, + documentation => 'SSL authentication level', + }, + SSLVar => { type => 'text', }, + + # CAS + CAS_authnLevel => { + type => 'int', + default => 1, + documentation => 'CAS authentication level', + }, + CAS_url => { + type => 'text', + test => qr/^$RE{URI}{HTTP}{-scheme=>"https?"}$/, + msgFail => '__badUrl__', + }, + CAS_CAFile => { type => 'text', }, + CAS_renew => { type => 'bool', }, + CAS_gateway => { type => 'bool', }, + CAS_pgtFile => { + type => 'text', + default => '/tmp/pgt.txt', + documentation => 'CAS PGT file', + }, + CAS_proxiedServices => { + type => 'keyTextContainer', + keyTest => qr/^\w+$/, + keyMsgFail => 'Bad CAS proxied service identifier', + }, + + # Radius + radiusAuthnLevel => { + type => 'int', + default => 3, + documentation => 'Radius authentication level', + }, + radiusSecret => { type => 'text', }, + radiusServer => { type => 'text', }, + + # Remote + remotePortal => { type => 'text', }, + remoteGlobalStorage => { + type => 'PerlModule', + default => 'Lemonldap::NG::Common::Apache::Session::SOAP', + documentation => 'Remote session backend', + }, + remoteGlobalStorageOptions => { + type => 'keyTextContainer', + default => { + proxy => 'http://auth.example.com/index.pl/sessions', + ns => + 'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService', + }, + documentation => 'Demo exported variables', + }, + + # Proxy + soapAuthService => { type => 'text', }, + remoteCookieName => { type => 'text', }, + soapSessionService => { type => 'text', }, + + # OpenID + openIdAuthnLevel => { + type => 'int', + default => 1, + documentation => 'OpenID authentication level', + }, + openIdSecret => { type => 'text', }, + openIdExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => {}, + documentation => 'OpenID exported variables', + }, + 'openIdIDPList' => { 'type' => 'blackWhiteList', default => '0;' }, + + # Google + googleAuthnLevel => { + type => 'int', + default => 1, + documentation => 'Google authentication level', + }, + googleExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => {}, + documentation => 'Google exported variables', + }, + + # Facebook + facebookAuthnLevel => { + type => 'int', + default => 1, + documentation => 'Facebook authentication level', + }, + facebookAppId => { type => 'text', }, + facebookAppSecret => { type => 'text', }, + facebookExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => {}, + documentation => 'Facebook exported variables', + }, + + # Twitter + twitterAuthnLevel => { + type => 'int', + default => 1, + documentation => 'Twitter authentication level', + }, + twitterKey => { type => 'text', }, + twitterSecret => { type => 'text', }, + twitterAppName => { type => 'text', }, + + # WebID + webIDAuthnLevel => { + type => 'int', + default => 1, + documentation => 'WebID authentication level', + }, + webIDWhitelist => { type => 'text', }, + webIDExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => {}, + documentation => 'WebID exported variables', + }, + + # DBI + dbiAuthnLevel => { + type => 'int', + default => 2, + documentation => 'DBI authentication level', + }, + dbiAuthChain => { type => 'text', }, + dbiAuthUser => { type => 'text', }, + dbiAuthPassword => { type => 'password', }, + dbiUserChain => { type => 'text', }, + dbiUserUser => { type => 'text', }, + dbiUserPassword => { type => 'password', }, + dbiAuthTable => { type => 'text', }, + dbiUserTable => { type => 'text', }, + dbiAuthLoginCol => { type => 'text', }, + dbiAuthPasswordCol => { type => 'text', }, + dbiPasswordMailCol => { type => 'text', }, + userPivot => { type => 'text', }, + dbiAuthPasswordHash => + { type => 'text', help => 'authdbi.html#password', }, + dbiExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => {}, + documentation => 'DBI exported variables', + }, + + # Apache + apacheAuthnLevel => { + type => 'int', + default => 4, + documentation => 'Apache authentication level', + }, + + # Null + nullAuthnLevel => { + type => 'int', + default => 2, + documentation => 'Null authentication level', + }, + + # Slave + slaveAuthnLevel => { + type => 'int', + default => 2, + documentation => 'Slave authentication level', + }, + slaveUserHeader => { type => 'text', }, + slaveExportedVars => { + type => 'keyTextContainer', + keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/, + keyMsgFail => 'Bad variable name', + test => qr/^[a-zA-Z][a-zA-Z0-9_:\-]*$/, + msgFail => '__badValue__', + default => {}, + documentation => 'Slave exported variables', + }, + slaveMasterIP => { + type => 'text', + test => qr/^$Regexp::Common::URI::RFC2396::IPv4address$/, + msgFail => '__badIPv4Address__', + }, + + # Choice + authChoiceParam => { + type => 'text', + default => 'lmAuth', + documentation => 'Applications list', + }, + authChoiceModules => { + type => 'authChoiceContainer', + keyTest => qr/^(\d*)?[a-zA-Z0-9_]+$/, + keyMsgFail => 'Bad choice key', + select => [ + [ + { k => 'Apache', v => 'Apache' }, + { k => 'AD', v => 'Active Directory' }, + { k => 'BrowserID', v => 'BrowserID (Mozilla Persona)' }, + { k => 'CAS', v => 'Central Authentication Service (CAS)' }, + { k => 'DBI', v => 'Database (DBI)' }, + { k => 'Facebook', v => 'Facebook' }, + { k => 'Google', v => 'Google' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Null', v => 'None' }, + { k => 'OpenID', v => 'OpenID' }, + { k => 'OpenIDConnect', v => 'OpenID Connect' }, + { k => 'Proxy', v => 'Proxy' }, + { k => 'Radius', v => 'Radius' }, + { k => 'Remote', v => 'Remote' }, + { k => 'SAML', v => 'SAML v2' }, + { k => 'Slave', v => 'Slave' }, + { k => 'SSL', v => 'SSL' }, + { k => 'Twitter', v => 'Twitter' }, + { k => 'WebID', v => 'WebID' }, + { k => 'Yubikey', v => 'Yubikey' } + ], + [ + { k => 'AD', v => 'Active Directory' }, + { k => 'DBI', v => 'Database (DBI)' }, + { k => 'Facebook', v => 'Facebook' }, + { k => 'Google', v => 'Google' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Null', v => 'None' }, + { k => 'OpenID', v => 'OpenID' }, + { k => 'OpenIDConnect', v => 'OpenID Connect' }, + { k => 'Proxy', v => 'Proxy' }, + { k => 'Remote', v => 'Remote' }, + { k => 'SAML', v => 'SAML v2' }, + { k => 'Slave', v => 'Slave' }, + { k => 'WebID', v => 'WebID' } + ], + [ + { k => 'AD', v => 'Active Directory' }, + { k => 'Choice', v => 'authChoice' }, + { k => 'DBI', v => 'Database (DBI)' }, + { k => 'LDAP', v => 'LDAP' }, + { k => 'Null', v => 'None' } + ] + ], + }, + + # Multi + multiAuthStack => { + type => 'authParamsText', + }, + multiUserDBStack => { + type => 'authParamsText', + }, + multiValuesSeparator => { + type => 'authParamsText', + default => '; ', + documentation => 'Separator for multiple values', + }, + + # Yubikey + yubikeyAuthnLevel => { + type => 'int', + default => 3, + documentation => 'Yubikey authentication level', + }, + yubikeyClientID => { type => 'text', }, + yubikeySecretKey => { type => 'text', }, + yubikeyPublicIDSize => { + type => 'int', + default => 12, + documentation => 'Yubikey public ID size', + }, + + # BrowserID + browserIdAuthnLevel => { + type => 'int', + default => 1, + documentation => 'Browser ID authentication level', + }, + browserIdAutoLogin => { type => 'bool', }, + browserIdVerificationURL => { type => 'text', }, + browserIdSiteName => { type => 'text', }, + browserIdSiteLogo => { type => 'text', }, + browserIdBackgroundColor => { type => 'text', }, + + # OpenID Connect auth params + oidcAuthnLevel => { + type => 'int', + default => 1, + documentation => 'OpenID Connect authentication level', + }, + oidcRPCallbackGetParam => { + type => 'text', + default => 'openidconnectcallback', + documentation => 'OpenID Connect Callback GET URLparameter', + }, + oidcRPStateTimeout => { + type => 'int', + default => 600, + documentation => 'OpenID Connect Timeout of state sessions', + }, + + # OpenID Connect service + oidcServiceMetaDataIssuer => { + type => 'text', + documentation => 'OpenID Connect end session endpoint', + }, + oidcServiceMetaDataAuthorizeURI => { + type => 'text', + default => 'authorize', + documentation => 'OpenID Connect authorizaton endpoint', + }, + oidcServiceMetaDataTokenURI => { + type => 'text', + default => 'token', + documentation => 'OpenID Connect token endpoint', + }, + oidcServiceMetaDataUserInfoURI => { + type => 'text', + default => 'userinfo', + documentation => 'OpenID Connect user info endpoint', + }, + oidcServiceMetaDataJWKSURI => { + type => 'text', + default => 'jwks', + documentation => 'OpenID Connect JWKS endpoint', + }, + oidcServiceMetaDataRegistrationURI => { + type => 'text', + default => 'register', + documentation => 'OpenID Connect registration endpoint', + }, + oidcServiceMetaDataEndSessionURI => { + type => 'text', + default => 'logout', + documentation => 'OpenID Connect end session endpoint', + }, + oidcServiceMetaDataCheckSessionURI => { + type => 'text', + default => 'checksession', + documentation => 'OpenID Connect check session iframe', + }, + oidcServiceMetaDataAuthnContext => { + type => 'keyTextContainer', + default => { + 'loa-1' => 1, + 'loa-2' => 2, + 'loa-3' => 3, + 'loa-4' => 4, + 'loa-5' => 5, + }, + documentation => 'OpenID Connect Authentication Context Class Ref', + }, + oidcServicePrivateKeySig => { type => 'RSAPrivateKey', }, + oidcServicePublicKeySig => { type => 'RSAPublicKey', }, + oidcServiceKeyIdSig => { + type => 'text', + documentation => 'OpenID Connect Signature Key ID', + }, + oidcServiceAllowDynamicRegistration => { + type => 'bool', + default => '0', + documentation => 'OpenID Connect allow dynamic client registration', + }, + oidcServiceAllowAuthorizationCodeFlow => { + type => 'bool', + default => '1', + documentation => 'OpenID Connect allow authorization code flow', + }, + oidcServiceAllowImplicitFlow => { + type => 'bool', + default => '0', + documentation => 'OpenID Connect allow implicit flow', + }, + oidcServiceAllowHybridFlow => { + type => 'bool', + default => '0', + documentation => 'OpenID Connect allow hybrid flow', + }, + oidcStorage => { type => 'PerlModule', }, + oidcStorageOptions => { + type => 'keyTextContainer', + }, + + # OpenID Connect metadata nodes + oidcOPMetaDataNodes => + { type => 'oidcOPMetaDataNodeContainer', help => 'oidcop.html', }, + oidcRPMetaDataNodes => + { type => 'oidcRPMetaDataNodeContainer', help => 'oidcrp.html', }, + oidcOPMetaDataOptions => { type => 'subContainer', }, + oidcRPMetaDataOptions => { type => 'subContainer', }, + + # OpenID Connect providers + oidcOPMetaDataJSON => { type => 'file', }, + oidcOPMetaDataJWKS => { type => 'file', }, + oidcOPMetaDataExportedVars => { type => 'keyTextContainer', }, + oidcOPMetaDataOptionsConfigurationURI => { type => 'text', }, + oidcOPMetaDataOptionsJWKSTimeout => { type => 'int', }, + oidcOPMetaDataOptionsClientID => { type => 'text', }, + oidcOPMetaDataOptionsClientSecret => { type => 'password', }, + oidcOPMetaDataOptionsScope => { type => 'text', }, + oidcOPMetaDataOptionsDisplay => { type => 'text', }, + oidcOPMetaDataOptionsPrompt => { type => 'text', }, + oidcOPMetaDataOptionsMaxAge => { type => 'int', }, + oidcOPMetaDataOptionsUiLocales => { type => 'text', }, + oidcOPMetaDataOptionsAcrValues => { type => 'text', }, + oidcOPMetaDataOptionsTokenEndpointAuthMethod => { type => 'text', }, + oidcOPMetaDataOptionsCheckJWTSignature => { type => 'bool', }, + oidcOPMetaDataOptionsIDTokenMaxAge => { type => 'int', }, + oidcOPMetaDataOptionsUseNonce => { type => 'bool', }, + oidcOPMetaDataOptionsDisplayName => { type => 'text', }, + oidcOPMetaDataOptionsIcon => { type => 'text', }, + + # OpenID Connect relying parties + oidcRPMetaDataExportedVars => { type => 'keyTextContainer', }, + oidcRPMetaDataOptionsClientID => { type => 'text', }, + oidcRPMetaDataOptionsClientSecret => { type => 'password', }, + oidcRPMetaDataOptionsDisplayName => { type => 'text', }, + oidcRPMetaDataOptionsIcon => { type => 'text', }, + oidcRPMetaDataOptionsUserIDAttr => { type => 'text', }, + oidcRPMetaDataOptionsIDTokenSignAlg => { type => 'text', }, + oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int', }, + oidcRPMetaDataOptionsAccessTokenExpiration => { type => 'int', }, + oidcRPMetaDataOptionsRedirectUris => { type => 'text', }, + oidcRPMetaDataOptionsExtraClaims => { type => 'keyTextContainer', }, + + }; +} + +1; diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/CTrees.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/CTrees.pm similarity index 98% rename from lemonldap-ng-manager/lib/Lemonldap/NG/Manager/CTrees.pm rename to lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/CTrees.pm index 62d161188..e8a77462c 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/CTrees.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/CTrees.pm @@ -8,11 +8,11 @@ # # Conf parameters are just strings in the `nodes` array # -# All other ideas have to be set in Common/Conf/Attributes.pm ! +# All other ideas have to be set in Manager/Build/Attributes.pm ! # DON'T FORGET TO RUN jsongenerator.pl AFTER EACH CHANGE -package Lemonldap::NG::Manager::CTrees; +package Lemonldap::NG::Manager::Build::CTrees; sub cTrees { return { diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Tree.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Tree.pm similarity index 99% rename from lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Tree.pm rename to lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Tree.pm index a5227746f..8f5e02ede 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Tree.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Tree.pm @@ -7,11 +7,11 @@ # # Conf parameters are just strings in the `nodes` array # -# All other ideas have to be set in Common/Conf/Attributes.pm ! +# All other ideas have to be set in Manager/Build/Attributes.pm ! # DON'T FORGET TO RUN jsongenerator.pl AFTER EACH CHANGE -package Lemonldap::NG::Manager::Tree; +package Lemonldap::NG::Manager::Build::Tree; our $VERSION = '1.9.0'; diff --git a/lemonldap-ng-manager/scripts/jsongenerator.pl b/lemonldap-ng-manager/scripts/jsongenerator.pl index 9a7fa36bd..03c527bdc 100755 --- a/lemonldap-ng-manager/scripts/jsongenerator.pl +++ b/lemonldap-ng-manager/scripts/jsongenerator.pl @@ -2,9 +2,9 @@ use strict; -use Lemonldap::NG::Manager::Attributes; -use Lemonldap::NG::Manager::Tree; -use Lemonldap::NG::Manager::CTrees; +use Lemonldap::NG::Manager::Build::Attributes; +use Lemonldap::NG::Manager::Build::Tree; +use Lemonldap::NG::Manager::Build::CTrees; #use Lemonldap::NG::Manager; use Data::Dumper; @@ -29,6 +29,7 @@ my $confTreeFile = "site/static/js/conftree.js"; my $managerConstants = "lib/Lemonldap/NG/Manager/Constants.pm"; my $defaultValuesFile = "../lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm"; +my $managerAttributesFile = 'lib/Lemonldap/NG/Manager/Attributes.pm'; my @simpleHashKeys; my @sessionTypes; my @cnodesKeys; @@ -51,7 +52,7 @@ $Data::Dumper::Sortkeys = sub { ]; }; -my $attributes = Lemonldap::NG::Manager::Attributes::attributes(); +my $attributes = Lemonldap::NG::Manager::Build::Attributes::attributes(); my $jsonEnc = JSON->new()->allow_nonref; my $mainTree; my @ignoreKeys; @@ -62,7 +63,7 @@ $jsonEnc->canonical(1); # 1. confTree.js unless ( $opts{f} ) { - $mainTree = Lemonldap::NG::Manager::CTrees::cTrees(); + $mainTree = Lemonldap::NG::Manager::Build::CTrees::cTrees(); my $script = 'function templates(tpl,key){' @@ -75,7 +76,7 @@ unless ( $opts{f} ) { . 'switch(tpl){'; # To build confTree.js, each special node is scanned from - # Lemonldap::NG::Manager::CTrees + # Lemonldap::NG::Manager::Build::CTrees foreach my $node ( sort keys $mainTree ) { @cnodesKeys = (); my $jsonTree = []; @@ -111,7 +112,7 @@ unless ( $opts{f} ) { } # 2. struct.json -$mainTree = Lemonldap::NG::Manager::Tree::tree(); +$mainTree = Lemonldap::NG::Manager::Build::Tree::tree(); my $jsonTree = []; &scanTree( $mainTree, $jsonTree, '', '' ); my $script = 'function setScopeVars(scope){'; @@ -144,7 +145,7 @@ use strict; use Exporter 'import'; use base qw(Exporter); -our \$VERSION = '$Lemonldap::NG::Manager::Attributes::VERSION'; +our \$VERSION = '$Lemonldap::NG::Manager::Build::Attributes::VERSION'; our %EXPORT_TAGS = ( 'all' => [qw($exportedVars)] ); our \@EXPORT_OK = ( \@{ \$EXPORT_TAGS{'all'} } ); @@ -183,11 +184,35 @@ my $defaultValues = { } keys(%$attributes) }; my $defaultAttr = Dumper($defaultValues); +my $managerAttr = { + map { + my @r; + foreach my $f (qw(keyTest type test msgFail default)) { + push @r, $f, $attributes->{$_}->{$f} + if ( defined $attributes->{$_}->{$f} ); + } + ( $_ => {@r} ); + } keys(%$attributes) +}; +$managerAttr = Dumper($managerAttr); +$managerAttr =~ s/^\$VAR1\s*=/sub attributes {\n return/; +my $managerTypes = Dumper(Lemonldap::NG::Manager::Build::Attributes::types()); +$managerTypes =~ s/^\$VAR1\s*=/sub types {\n return/; +$managerAttr = "# This file is generated by $0. Don't modify it by hand +package Lemonldap::NG::Manager::Attributes; + +our \$VERSION = '$Lemonldap::NG::Manager::Build::Attributes::VERSION'; + +$managerTypes} + +$managerAttr} + +"; $defaultAttr =~ s/^\$VAR1\s*=/sub defaultValues {\n return/; $defaultAttr = "# This file is generated by $0. Don't modify it by hand package Lemonldap::NG::Common::Conf::DefaultValues; -our \$VERSION = '$Lemonldap::NG::Manager::Attributes::VERSION'; +our \$VERSION = '$Lemonldap::NG::Manager::Build::Attributes::VERSION'; $defaultAttr} @@ -198,6 +223,17 @@ my $dst; eval { require Perl::Tidy; + Perl::Tidy::perltidy( + source => IO::String->new($managerAttr), + destination => \$dst + ); +}; +$dst = $managerAttr if ($@); + +open( F, "> $managerAttributesFile" ) or die($!); +print F $dst; +close F; +eval { Perl::Tidy::perltidy( source => IO::String->new($defaultAttr), destination => \$dst @@ -273,7 +309,8 @@ sub scanTree { if ( $leaf =~ s/^\*// ) { push @angularScopeVars, [ $leaf, "$path._nodes[$ord]" ]; } - push @sessionTypes, $1 if ( $leaf =~ /^(.*)(?{$leaf} or die("Missing attribute $leaf"); $jleaf = { id => "$prefix$leaf", title => $leaf }; unless ( $attr->{type} ) { diff --git a/lemonldap-ng-manager/site/static/forms/README.md b/lemonldap-ng-manager/site/static/forms/README.md index 01d48f147..89fe13403 100644 --- a/lemonldap-ng-manager/site/static/forms/README.md +++ b/lemonldap-ng-manager/site/static/forms/README.md @@ -3,10 +3,10 @@ This files contains the form used to expose configuration attributes. The form is chosen by looking at the *type* property of the current data. -This property is defined in `Lemonldap::NG::Manager::Attributes` package. +This property is defined in `Lemonldap::NG::Manager::Build::Attributes` package. By default, it is set to *text*. -`Lemonldap::NG::Manager::Attributes` is compiled into JSON/JS files by +`Lemonldap::NG::Manager::Build::Attributes` is compiled into JSON/JS files by `jsongenerator.pl`script. ## 1. Form file architecture diff --git a/lemonldap-ng-manager/t/03-HTML-forms.t b/lemonldap-ng-manager/t/03-HTML-forms.t index e3d99869f..e2871e932 100644 --- a/lemonldap-ng-manager/t/03-HTML-forms.t +++ b/lemonldap-ng-manager/t/03-HTML-forms.t @@ -7,9 +7,9 @@ use 5.10.0; my $formDir = 'site/static/forms'; my $count = 0; -use_ok('Lemonldap::NG::Manager::Tree'); -use_ok('Lemonldap::NG::Manager::CTrees'); -use_ok('Lemonldap::NG::Manager::Attributes'); +use_ok('Lemonldap::NG::Manager::Build::Tree'); +use_ok('Lemonldap::NG::Manager::Build::CTrees'); +use_ok('Lemonldap::NG::Manager::Build::Attributes'); $count += 3; ok( opendir( D, $formDir ), 'Found forms dir' ); @@ -20,9 +20,9 @@ delete $forms{white}; delete $forms{restore}; my ( @types, $attr, $tree, $ctrees ); -ok( $tree = Lemonldap::NG::Manager::Tree::tree(), 'Get tree' ); -ok( $ctrees = Lemonldap::NG::Manager::CTrees::cTrees(), 'Get cTrees' ); -ok( $attr = Lemonldap::NG::Manager::Attributes::attributes(), +ok( $tree = Lemonldap::NG::Manager::Build::Tree::tree(), 'Get tree' ); +ok( $ctrees = Lemonldap::NG::Manager::Build::CTrees::cTrees(), 'Get cTrees' ); +ok( $attr = Lemonldap::NG::Manager::Build::Attributes::attributes(), 'Get attributes' ); $count += 4; diff --git a/lemonldap-ng-manager/t/90-translations.t b/lemonldap-ng-manager/t/90-translations.t index 32eed2cb4..b5d881e71 100644 --- a/lemonldap-ng-manager/t/90-translations.t +++ b/lemonldap-ng-manager/t/90-translations.t @@ -8,9 +8,9 @@ use 5.10.0; my $langDir = 'site/static/languages'; my $count = 0; -use_ok('Lemonldap::NG::Manager::Tree'); -use_ok('Lemonldap::NG::Manager::CTrees'); -use_ok('Lemonldap::NG::Manager::Attributes'); +use_ok('Lemonldap::NG::Manager::Build::Tree'); +use_ok('Lemonldap::NG::Manager::Build::CTrees'); +use_ok('Lemonldap::NG::Manager::Build::Attributes'); $count += 3; ok( opendir( D, $langDir ), 'Found languages dir' ); @@ -60,7 +60,7 @@ foreach my $lang (@langs) { } my $tree; -ok( $tree = Lemonldap::NG::Manager::Tree::tree(), 'Get tree' ); +ok( $tree = Lemonldap::NG::Manager::Build::Tree::tree(), 'Get tree' ); my @nodes = @{ getNodes($tree) }; my @unTr; @@ -75,7 +75,7 @@ $count += 2; my ( $type, $ctrees ); @unTr = (); -ok( $ctrees = Lemonldap::NG::Manager::CTrees::cTrees(), 'Get cTrees' ); +ok( $ctrees = Lemonldap::NG::Manager::Build::CTrees::cTrees(), 'Get cTrees' ); while ( ( $type, $tree ) = each %$ctrees ) { @nodes = @{ getNodes($tree) }; foreach (@nodes) {