Attributes.pm 116 KB
Newer Older
Christophe Maudoux's avatar
Christophe Maudoux committed
1
#  This file contains the description of all configuration parameters
2 3 4
# It may be included only by batch files, never in portal or handler chain
# for performances reasons

Xavier Guimard's avatar
Xavier Guimard committed
5
# DON'T FORGET TO RUN "make json" AFTER EACH CHANGE
6 7 8

package Lemonldap::NG::Manager::Build::Attributes;

9
our $VERSION = '2.0.0';
10 11 12 13
use strict;
use Regexp::Common qw/URI/;

my $perlExpr = sub {
14
    my ( $val, $conf ) = @_;
15
    my $s = '';
Xavier Guimard's avatar
Xavier Guimard committed
16
    no warnings( 'redefine', 'uninitialized' );
17
    eval "$s $val";
18 19 20
    my $err = join( '',
        grep { $_ =~ /Undefined subroutine/ ? () : $_ } split( /\n/, $@ ) );
    return $err ? ( 1, "__badExpression__: $err" ) : (1);
21 22
};

Xavier Guimard's avatar
Xavier Guimard committed
23
my $url = $RE{URI}{HTTP}{ -scheme => "https?" };
Xavier Guimard's avatar
Xavier Guimard committed
24 25 26
$url =~ s/(?<=[^\\])\$/\\\$/g;
$url = qr/$url/;

27 28 29 30 31
sub types {
    return {

        # Simple text types
        text => {
Clément OUDOT's avatar
Clément OUDOT committed
32
            test    => sub { 1 },
33 34 35
            msgFail => '__malformedValue__',
        },
        password => {
Clément OUDOT's avatar
Clément OUDOT committed
36
            test    => sub { 1 },
37 38 39
            msgFail => '__malformedValue__',
        },
        longtext => {
Clément OUDOT's avatar
Clément OUDOT committed
40
            test => sub { 1 }
41 42 43
        },
        url => {
            form    => 'text',
Xavier Guimard's avatar
Xavier Guimard committed
44
            test    => $url,
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
            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 {
Clément OUDOT's avatar
Clément OUDOT committed
60
                eval { qr/$_[0]/ };
61 62 63 64 65
                return $@ ? ( 0, "__badRegexp__: $@" ) : (1);
            },
        },
        lmAttrOrMacro => {
            form => 'text',
Xavier Guimard's avatar
Xavier Guimard committed
66 67
            test => sub {
                my ( $val, $conf ) = @_;
68
                return 1
Clément OUDOT's avatar
Clément OUDOT committed
69
                  if ( defined $conf->{macros}->{$val}
70
                    or $val eq '_timezone' );
71 72
                foreach ( keys %$conf ) {
                    return 1
Clément OUDOT's avatar
Clément OUDOT committed
73
                      if ( $_ =~ /exportedvars$/i
74
                        and defined $conf->{$_}->{$val} );
Xavier Guimard's avatar
Xavier Guimard committed
75
                }
76
                return ( 1, "__unknownAttrOrMacro__: $val" );
Xavier Guimard's avatar
Xavier Guimard committed
77
            },
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        },

        # 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__',
        },
Xavier Guimard's avatar
Xavier Guimard committed
97 98
        keyTextContainer => {
            test       => qr/./,
Xavier Guimard's avatar
Xavier Guimard committed
99
            msgFail    => '__emptyValueNotAllowed__',
Xavier Guimard's avatar
Xavier Guimard committed
100
            keyTest    => qr/^\w[\w\.\-]*$/,
Xavier Guimard's avatar
Xavier Guimard committed
101
            keyMsgFail => '__badKeyName__',
Xavier Guimard's avatar
Xavier Guimard committed
102 103 104
        },
        subContainer => {
            keyTest => qr/\w/,
Clément OUDOT's avatar
Clément OUDOT committed
105
            test    => sub { 1 },
Xavier Guimard's avatar
Xavier Guimard committed
106
        },
Xavier Guimard's avatar
Xavier Guimard committed
107 108
        select => {
            test => sub {
109
                my $test = grep ( { $_ eq $_[0] }
Xavier Guimard's avatar
Xavier Guimard committed
110
                    map ( { $_->{k} } @{ $_[2]->{select} } ) );
Xavier Guimard's avatar
Xavier Guimard committed
111
                return $test
Clément OUDOT's avatar
Clément OUDOT committed
112 113
                  ? 1
                  : ( 1, "Invalid value '$_[0]' for this select" );
Xavier Guimard's avatar
Xavier Guimard committed
114 115
            },
        },
116 117 118

        # Files type (long text)
        file => {
Clément OUDOT's avatar
Clément OUDOT committed
119
            test => sub { 1 }
120 121
        },
        RSAPublicKey => {
122
            test => sub {
123
                return (
Clément OUDOT's avatar
Clément OUDOT committed
124 125
                    $_[0] =~
/^(?:(?:\-+\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
126
                    ? (1)
127 128
                    : ( 1, '__badPemEncoding__' )
                );
129
            },
130
        },
131
        'RSAPublicKeyOrCertificate' => {
132
            'test' => sub {
133
                return (
Clément OUDOT's avatar
Clément OUDOT committed
134 135
                    $_[0] =~
/^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+)?[\r\n]*)?$/s
136
                    ? (1)
137 138
                    : ( 1, '__badPemEncoding__' )
                );
139
            },
140
        },
141
        RSAPrivateKey => {
142
            test => sub {
143
                return (
Clément OUDOT's avatar
Clément OUDOT committed
144 145
                    $_[0] =~
/^(?:(?:\-+\s*BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY\s*\-+\r?\n)?(?:Proc-Type:.*\r?\nDEK-Info:.*\r?\n[\r\n]*)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+(?:RSA\s+)PRIVATE\s+KEY\s*\-+)?[\r\n]*)?$/s
146
                    ? (1)
147 148
                    : ( 1, '__badPemEncoding__' )
                );
149
            },
150 151 152
        },

        authParamsText => {
Clément OUDOT's avatar
Clément OUDOT committed
153
            test => sub { 1 }
154 155
        },
        blackWhiteList => {
Clément OUDOT's avatar
Clément OUDOT committed
156
            test => sub { 1 }
157 158
        },
        catAndAppList => {
Clément OUDOT's avatar
Clément OUDOT committed
159
            test => sub { 1 }
160 161 162
        },
        keyText => {
            keyTest => qr/^[a-zA-Z0-9_]+$/,
Xavier Guimard's avatar
Xavier Guimard committed
163
            test    => qr/^.*$/,
164 165 166
            msgFail => '__badValue__',
        },
        menuApp => {
Clément OUDOT's avatar
Clément OUDOT committed
167
            test => sub { 1 }
168 169
        },
        menuCat => {
Clément OUDOT's avatar
Clément OUDOT committed
170
            test => sub { 1 }
171 172
        },
        oidcOPMetaDataNode => {
Clément OUDOT's avatar
Clément OUDOT committed
173
            test => sub { 1 }
174 175
        },
        oidcRPMetaDataNode => {
Clément OUDOT's avatar
Clément OUDOT committed
176
            test => sub { 1 }
177 178
        },
        oidcmetadatajson => {
Clément OUDOT's avatar
Clément OUDOT committed
179
            test => sub { 1 }
180 181
        },
        oidcmetadatajwks => {
Clément OUDOT's avatar
Clément OUDOT committed
182
            test => sub { 1 }
183 184
        },
        portalskin => {
Clément OUDOT's avatar
Clément OUDOT committed
185
            test => sub { 1 }
186 187
        },
        portalskinbackground => {
Clément OUDOT's avatar
Clément OUDOT committed
188
            test => sub { 1 }
189 190
        },
        post => {
Clément OUDOT's avatar
Clément OUDOT committed
191
            test => sub { 1 }
192 193
        },
        rule => {
Clément OUDOT's avatar
Clément OUDOT committed
194
            test => sub { 1 }
195 196
        },
        samlAssertion => {
Clément OUDOT's avatar
Clément OUDOT committed
197
            test => sub { 1 }
198 199
        },
        samlAttribute => {
Clément OUDOT's avatar
Clément OUDOT committed
200
            test => sub { 1 }
201 202
        },
        samlIDPMetaDataNode => {
Clément OUDOT's avatar
Clément OUDOT committed
203
            test => sub { 1 }
204 205
        },
        samlSPMetaDataNode => {
Clément OUDOT's avatar
Clément OUDOT committed
206
            test => sub { 1 }
207 208
        },
        samlService => {
Clément OUDOT's avatar
Clément OUDOT committed
209
            test => sub { 1 }
210
        },
211
        array => {
Clément OUDOT's avatar
Clément OUDOT committed
212
            test => sub { 1 }
213
        },
214 215 216 217 218 219 220
    };
}

sub attributes {
    return {

        # Other
221 222 223
        checkTime => {
            type => 'int',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
224
              'Timeout to check new configuration in local cache',
225
            default => 600,
226 227 228 229 230 231
            flags   => 'hp',
        },
        mySessionAuthorizedRWKeys => {
            type          => 'array',
            documentation => 'Alterable session keys by user itself',
            default =>
Clément OUDOT's avatar
Clément OUDOT committed
232
              [ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
233
        },
Xavier Guimard's avatar
Xavier Guimard committed
234 235 236 237 238 239 240 241 242 243 244 245
        configStorage => {
            type          => 'text',
            documentation => 'Configuration storage',
            flags         => 'hmp',
        },
        localStorage => {
            type          => 'text',
            documentation => 'Local cache',
            flags         => 'hmp',
        },
        localStorageOptions => {
            type          => 'keyTextContainer',
Xavier Guimard's avatar
Xavier Guimard committed
246
            documentation => 'Local cache parameters',
Xavier Guimard's avatar
Xavier Guimard committed
247 248
            flags         => 'hmp',
        },
249 250 251 252 253 254
        cfgNum => {
            type          => 'int',
            default       => 0,
            documentation => 'Enable Cross Domain Authentication',
        },
        cfgAuthor => {
Clément OUDOT's avatar
Clément OUDOT committed
255 256
            type          => 'text',
            documentation => 'Name of the author of the current configuration',
257 258
        },
        cfgAuthorIP => {
Clément OUDOT's avatar
Clément OUDOT committed
259 260
            type          => 'text',
            documentation => 'Uploader IP address of the current configuration',
261 262 263 264 265 266 267 268 269
        },
        cfgDate => {
            type          => 'int',
            documentation => 'Timestamp of the current configuration',
        },
        cfgLog => {
            type          => 'longtext',
            documentation => 'Configuration update log',
        },
270 271 272 273
        cfgVersion => {
            type          => 'text',
            documentation => 'Version of LLNG which build configuration',
        },
Xavier Guimard's avatar
Xavier Guimard committed
274 275 276 277 278
        status => {
            type          => 'bool',
            documentation => 'Status daemon activation',
            flags         => 'h',
        },
279 280 281
        confirmFormMethod => {
            type => "select",
            select =>
Clément OUDOT's avatar
Clément OUDOT committed
282
              [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
283 284 285
            default       => 'post',
            documentation => 'HTTP method for confirm page form',
        },
286 287
        customFunctions => {
            type          => 'text',
288
            test          => qr/^(?:\w+(?:::\w+)*(?:\s+\w+(?:::\w+)*)*)?$/,
289
            help          => 'customfunctions.html',
290
            msgFail       => "__badCustomFuncName__",
Xavier Guimard's avatar
Xavier Guimard committed
291 292
            documentation => 'List of custom functions',
            flags         => 'hmp',
293 294
        },
        https => {
295 296 297
            default       => 0,
            type          => 'bool',
            documentation => 'Use HTTPS for redirection from portal',
Xavier Guimard's avatar
Xavier Guimard committed
298
            flags         => 'h',
299 300 301 302
        },
        infoFormMethod => {
            type => "select",
            select =>
Clément OUDOT's avatar
Clément OUDOT committed
303
              [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
304 305 306
            default       => 'get',
            documentation => 'HTTP method for info page form',
        },
Xavier Guimard's avatar
Xavier Guimard committed
307 308 309 310 311
        port => {
            type          => 'int',
            documentation => 'Force port in redirection',
            flags         => 'h',
        },
312 313 314 315 316 317
        jsRedirect => {
            type          => 'boolOrExpr',
            default       => 0,
            documentation => 'Use javascript for redirections',
        },
        logoutServices => {
Clément OUDOT's avatar
Clément OUDOT committed
318 319 320 321
            type          => 'keyTextContainer',
            help          => 'logoutforward.html',
            default       => {},
            documentation => 'Send logout trough GET request to these services',
322 323 324 325 326
        },
        maintenance => {
            default       => 0,
            type          => 'bool',
            documentation => 'Maintenance mode for all virtual hosts',
Xavier Guimard's avatar
Xavier Guimard committed
327
            flags         => 'h',
328
        },
Xavier Guimard's avatar
Xavier Guimard committed
329 330 331 332
        nginxCustomHandlers => {
            type    => 'keyTextContainer',
            keyTest => qr/^\w+$/,
            test    => qr/^[a-zA-Z][a-zA-Z0-9]*(?:::[a-zA-Z][a-zA-Z0-9]*)*$/,
333
            help    => 'handlerarch.html',
Xavier Guimard's avatar
Xavier Guimard committed
334
            msgFail => '__badPerlPackageName__',
Xavier Guimard's avatar
Xavier Guimard committed
335
            documentation => 'Custom Nginx handler (deprecated)',
Xavier Guimard's avatar
Xavier Guimard committed
336
        },
337 338 339 340 341
        noAjaxHook => {
            default       => 0,
            type          => 'bool',
            documentation => 'Avoid replacing 302 by 401 for Ajax responses',
        },
342 343 344 345
        portal => {
            type          => 'url',
            default       => 'http://auth.example.com/',
            documentation => 'Portal URL',
Xavier Guimard's avatar
Xavier Guimard committed
346
            flags         => 'hmp',
347 348
            test          => $url,
            msgFail       => '__badUrl__',
349
        },
350 351 352 353 354
        portalStatus => {
            type          => 'bool',
            default       => 0,
            documentation => 'Enable portal status',
        },
355 356 357
        portalUserAttr => {
            type    => 'text',
            default => '_user',
358
            help    => 'monitoring.html',
359
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
360
              'Session parameter to display connected user in portal',
361 362 363 364
        },
        redirectFormMethod => {
            type => "select",
            select =>
Clément OUDOT's avatar
Clément OUDOT committed
365
              [ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
366 367 368 369
            default       => 'get',
            documentation => 'HTTP method for redirect page form',
        },
        reloadUrls => {
Clément OUDOT's avatar
Clément OUDOT committed
370 371 372 373 374
            type          => 'keyTextContainer',
            help          => 'configlocation.html#configuration_reload',
            keyTest       => qr/^$Regexp::Common::URI::RFC2396::host(?::\d+)?$/,
            test          => $url,
            msgFail       => '__badUrl__',
Xavier Guimard's avatar
Xavier Guimard committed
375
            documentation => 'URL to call on reload',
376
        },
Clément OUDOT's avatar
Clément OUDOT committed
377
        portalMainLogo => {
378 379 380 381
            type          => 'text',
            default       => 'common/logos/logo_llng_400px.png',
            documentation => 'Portal main logo path',
        },
382 383 384 385 386
        showLanguages => {
            type          => 'bool',
            default       => 1,
            documentation => 'Display langs icons',
        },
387 388 389 390
        staticPrefix => {
            type          => 'text',
            documentation => 'Prefix of static files for HTML templates',
        },
391 392 393 394
        multiValuesSeparator => {
            type          => 'authParamsText',
            default       => '; ',
            documentation => 'Separator for multiple values',
Xavier Guimard's avatar
Xavier Guimard committed
395
            flags         => 'hmp',
396
        },
397 398
        stayConnected => {
            type          => 'bool',
399
            default       => 0,
400 401
            documentation => 'Enable StayConnected plugin',
        },
402
        checkState => {
403
            type          => 'bool',
404
            default       => 0,
405 406
            documentation => 'Enable CheckState plugin',
        },
407
        checkStateSecret  => {
408
            type          => 'text',
409 410
            documentation => 'Secret token for CheckState plugin',
        },
411
        skipRenewConfirmation => {
412 413
            type          => 'bool',
            default       => 0,
414
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
415
              'Avoid asking confirmation when an Issuer asks to renew auth',
416
        },
417 418 419 420
        handlerInternalCache => {
            type          => 'int',
            default       => 15,
            documentation => 'Handler internal cache timeout',
Christophe Maudoux's avatar
Christophe Maudoux committed
421
            flags         => 'hp',
422
        },
423

424 425 426 427 428 429 430 431 432
        # Loggers (ini only)
        logLevel => {
            type          => 'text',
            documentation => 'Log level, must be set in .ini',
            flags         => 'hmp',
        },
        logger => {
            type          => 'text',
            documentation => 'technical logger',
433
            flags         => 'hmp',
434 435 436 437
        },
        userLogger => {
            type          => 'text',
            documentation => 'User actions logger',
438
            flags         => 'hmp',
439 440 441 442
        },
        log4perlConfFile => {
            type          => 'text',
            documentation => 'Log4Perl logger configuration file',
443
            flags         => 'hmp',
444 445 446 447
        },
        sentryDsn => {
            type          => 'text',
            documentation => 'Sentry logger DSN',
448
            flags         => 'hmp',
449 450 451 452
        },
        syslogFacility => {
            type          => 'text',
            documentation => 'Syslog logger technical facility',
453
            flags         => 'hmp',
454 455 456 457
        },
        userSyslogFacility => {
            type          => 'text',
            documentation => 'Syslog logger user-actions facility',
458
            flags         => 'hmp',
459 460 461
        },

        # Manager or PSGI protected apps
462
        protection => {
Clément OUDOT's avatar
Clément OUDOT committed
463 464 465
            type          => 'text',
            test          => qr/^(?:none|authenticate|manager|)$/,
            msgFail       => '__authorizedValues__: none authenticate manager',
466
            documentation => 'Manager protection method',
Xavier Guimard's avatar
Xavier Guimard committed
467
            flags         => 'hm',
468 469 470 471 472 473 474 475 476 477
        },

        # Menu
        activeTimer => {
            type          => 'bool',
            default       => 1,
            documentation => 'Enable timers on portal pages',
        },
        applicationList => {
            type    => 'catAndAppList',
478
            keyTest => qr/\w/,
479 480
            help    => 'portalmenu.html#categories_and_applications',
            default => {
Clément OUDOT's avatar
Clément OUDOT committed
481
                default => { catname => 'Default category', type => "category" }
482 483 484
            },
            documentation => 'Applications list',
        },
485 486 487 488 489
        portalErrorOnExpiredSession => {
            type          => 'bool',
            default       => 1,
            documentation => 'Show error if session is expired',
        },
490
        portalErrorOnMailNotFound => {
dcoutadeur dcoutadeur's avatar
dcoutadeur dcoutadeur committed
491 492 493
            type    => 'bool',
            default => 0,
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
494
              'Show error if mail is not found in password reset process',
495
        },
496 497 498 499 500 501 502 503 504 505 506 507 508 509
        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',
Xavier Guimard's avatar
Xavier Guimard committed
510
            select        => [ { k => 'bootstrap', v => 'Bootstrap' }, ],
511 512 513 514 515 516
        },
        portalSkinBackground => {
            type          => 'portalskinbackground',
            documentation => 'Background image of portal skin',
            select        => [
                { k => "", v => 'None' },
Clément OUDOT's avatar
Clément OUDOT committed
517 518
                {
                    k => "1280px-Anse_Source_d'Argent_2-La_Digue.jpg",
519 520
                    v => 'Anse'
                },
Clément OUDOT's avatar
Clément OUDOT committed
521 522 523
                {
                    k =>
"1280px-Autumn-clear-water-waterfall-landscape_-_Virginia_-_ForestWander.jpg",
524 525 526
                    v => 'Waterfall'
                },
                { k => "1280px-BrockenSnowedTrees.jpg", v => 'Snowed Trees' },
Clément OUDOT's avatar
Clément OUDOT committed
527 528
                {
                    k => "1280px-Cedar_Breaks_National_Monument_partially.jpg",
529 530
                    v => 'National Monument'
                },
Clément OUDOT's avatar
Clément OUDOT committed
531 532
                {
                    k => "1280px-Parry_Peak_from_Winter_Park.jpg",
533 534
                    v => 'Winter'
                },
Clément OUDOT's avatar
Clément OUDOT committed
535 536
                {
                    k => "Aletschgletscher_mit_Pinus_cembra1.jpg",
537 538
                    v => 'Pinus'
                },
539 540 541
            ],
        },
        portalSkinRules => {
Xavier Guimard's avatar
Xavier Guimard committed
542 543 544 545 546 547 548
            type          => 'keyTextContainer',
            help          => 'portalcustom.html',
            keyTest       => $perlExpr,
            keyMsgFail    => '__badSkinRule__',
            test          => qr/^\w+$/,
            msgFail       => '__badValue__',
            documentation => 'Rules to choose portal skin',
549 550 551
        },

        # Security
552
        formTimeout => {
Xavier Guimard's avatar
Xavier Guimard committed
553 554
            default       => 120,
            type          => 'int',
555 556 557
            documentation => 'Token timeout for forms',
        },
        requireToken => {
Xavier Guimard's avatar
Xavier Guimard committed
558 559
            default       => 1,
            type          => 'bool',
560 561
            documentation => 'Enable token for forms',
        },
562 563 564 565 566
        tokenUseGlobalStorage => {
            default       => 0,
            type          => 'bool',
            documentation => 'Enable global token storage',
        },
567 568 569 570
        cda => {
            default       => 0,
            type          => 'bool',
            documentation => 'Enable Cross Domain Authentication',
Xavier Guimard's avatar
Xavier Guimard committed
571
            flags         => 'hp',
572 573 574 575 576 577
        },
        checkXSS => {
            default       => 1,
            type          => 'bool',
            documentation => 'Check XSS',
        },
578
        portalForceAuthn => {
579
            default => 0,
580 581
            type    => 'bool',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
582
              'Enable force to authenticate when displaying portal',
583
        },
584 585
        portalForceAuthnInterval => {
            default => 5,
586 587
            type    => 'int',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
588
'Maximun interval in seconds since last authentifcation to force reauthentication',
589
        },
590
        bruteForceProtection => {
591
            default       => 0,
592 593 594 595 596 597 598
            type          => 'bool',
            documentation => 'Enable brute force attack protection',
        },
        bruteForceProtectionTempo => {
            default => 30,
            type    => 'int',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
599
              'Brute force attack protection -> Tempo before try again',
600 601 602 603 604
        },
        bruteForceProtectionMaxAge => {
            default => 300,
            type    => 'int',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
605
              'Brute force attack protection -> Max age third failed login',
606
        },
607
        grantSessionRules => {
Xavier Guimard's avatar
Xavier Guimard committed
608 609
            type          => 'grantContainer',
            keyTest       => $perlExpr,
Clément OUDOT's avatar
Clément OUDOT committed
610
            test          => sub { 1 },
Xavier Guimard's avatar
Xavier Guimard committed
611
            documentation => 'Rules to grant sessions',
612 613 614 615 616 617 618 619 620 621
        },
        hiddenAttributes => {
            type          => 'text',
            default       => '_password',
            documentation => 'Name of attributes to hide in logs',
        },
        key => {
            type          => 'password',
            documentation => 'Secret key',
        },
622 623
        cspDefault => {
            type          => 'text',
Xavier Guimard's avatar
Xavier Guimard committed
624
            default       => "'self'",
625 626
            documentation => 'Default value for Content-Security-Policy',
        },
627 628
        cspFormAction => {
            type          => 'text',
629
            default       => "'self'",
Christophe Maudoux's avatar
Typo  
Christophe Maudoux committed
630
            documentation => 'Form action destination for Content-Security-Policy',
631
        },
632 633
        cspImg => {
            type          => 'text',
634
            default       => "'self' data:",
635 636 637 638 639 640 641 642 643
            documentation => 'Image source for Content-Security-Policy',
        },
        cspScript => {
            type          => 'text',
            default       => "'self'",
            documentation => 'Javascript source for Content-Security-Policy',
        },
        cspStyle => {
            type          => 'text',
644
            default       => "'self'",
645 646 647 648 649 650
            documentation => 'Style source for Content-Security-Policy',
        },
        cspConnect => {
            type    => 'text',
            default => "'self'",
            documentation =>
Christophe Maudoux's avatar
Typo  
Christophe Maudoux committed
651
              'Authorized Ajax destination for Content-Security-Policy',
652 653 654 655 656 657
        },
        cspFont => {
            type          => 'text',
            default       => "'self'",
            documentation => 'Font source for Content-Security-Policy',
        },
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
        portalAntiFrame => {
            default       => 1,
            type          => 'bool',
            documentation => 'Avoid portal to be displayed inside frames',
        },
        portalCheckLogins => {
            default       => 1,
            type          => 'bool',
            documentation => 'Display login history checkbox in portal',
        },
        randomPasswordRegexp => {
            type          => 'pcre',
            default       => '[A-Z]{3}[a-z]{5}.\d{2}',
            documentation => 'Regular expression to create a random password',
        },
Xavier Guimard's avatar
Xavier Guimard committed
673
        trustedDomains =>
Clément OUDOT's avatar
Clément OUDOT committed
674
          { type => 'text', documentation => 'Trusted domains', },
Xavier Guimard's avatar
Xavier Guimard committed
675
        storePassword => {
676 677 678 679 680 681
            default       => 0,
            type          => 'bool',
            documentation => 'Store password in session',
        },
        timeout => {
            type          => 'int',
Xavier Guimard's avatar
Xavier Guimard committed
682
            test          => sub { $_[0] > 0 },
683 684 685 686
            default       => 72000,
            documentation => 'Session timeout on server side',
        },
        timeoutActivity => {
687
            type          => 'int',
Xavier Guimard's avatar
Xavier Guimard committed
688
            test          => sub { $_[0] >= 0 },
689 690 691
            default       => 0,
            documentation => 'Session activity timeout on server side',
        },
692 693 694 695 696 697
        timeoutActivityInterval => {
            type          => 'int',
            test          => sub { $_[0] >= 0 },
            default       => 60,
            documentation => 'Update session timeout interval on server side',
        },
698 699 700 701 702 703 704 705 706 707 708 709 710 711
        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)',
Xavier Guimard's avatar
Xavier Guimard committed
712
            flags         => 'h',
713 714 715 716 717 718 719 720 721
        },
        useRedirectOnForbidden => {
            default       => 0,
            type          => 'bool',
            documentation => 'Use 302 redirect code for forbidden (403)',
        },
        useSafeJail => {
            default       => 1,
            type          => 'bool',
Xavier Guimard's avatar
Xavier Guimard committed
722
            help          => 'safejail.html',
723
            documentation => 'Activate Safe jail',
Xavier Guimard's avatar
Xavier Guimard committed
724
            flags         => 'hp',
725 726 727 728 729
        },
        whatToTrace => {
            type          => 'lmAttrOrMacro',
            default       => 'uid',
            documentation => 'Session parameter used to fill REMOTE_USER',
Xavier Guimard's avatar
Xavier Guimard committed
730
            flags         => 'hp',
731
        },
732
        lwpOpts => {
Xavier Guimard's avatar
Xavier Guimard committed
733 734 735
            type          => 'keyTextContainer',
            documentation => 'Options given to LWP::UserAgent',
        },
736 737 738 739
        lwpSslOpts => {
            type          => 'keyTextContainer',
            documentation => 'SSL options given to LWP::UserAgent',
        },
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784

        # History
        failedLoginNumber => {
            default       => 5,
            type          => 'int',
            documentation => 'Number of failures stored in login history',
        },
        loginHistoryEnabled => {
            default       => 0,
            type          => 'bool',
            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 => {
785
            default       => 0,
786 787 788
            type          => 'bool',
            documentation => 'Display reset password button in portal',
        },
789
        passwordResetAllowedRetries => {
Christophe Maudoux's avatar
Christophe Maudoux committed
790
            default       => 3,
791 792 793
            type          => 'int',
            documentation => 'Maximum number of retries to reset password',
        },
794 795
        portalDisplayOidcConsents => {
            type          => 'boolOrExpr',
796
            default       => '$_oidcConnectedRP',
797 798
            documentation => 'Display OIDC consent tab in portal',
        },
799 800

        # Cookies
Xavier Guimard's avatar
Xavier Guimard committed
801
        cookieExpiration => {
802
            type          => 'int',
Xavier Guimard's avatar
Xavier Guimard committed
803 804 805
            documentation => 'Cookie expiration',
            flags         => 'hp',
        },
Xavier Guimard's avatar
Xavier Guimard committed
806
        cookieName => {
807 808 809 810 811
            type          => 'text',
            test          => qr/^[a-zA-Z][a-zA-Z0-9_-]*$/,
            msgFail       => '__badCookieName__',
            default       => 'lemonldap',
            documentation => 'Name of the main cookie',
Xavier Guimard's avatar
Xavier Guimard committed
812
            flags         => 'hp',
813 814
        },
        domain => {
Clément OUDOT's avatar
Clément OUDOT committed
815 816 817 818
            type          => 'text',
            test          => qr/^(?:$Regexp::Common::URI::RFC2396::hostname)?$/,
            msgFail       => '__badDomainName__',
            default       => 'example.com',
819
            documentation => 'DNS domain',
Xavier Guimard's avatar
Xavier Guimard committed
820
            flags         => 'hp',
821 822 823 824 825
        },
        httpOnly => {
            default       => 1,
            type          => 'bool',
            documentation => 'Enable httpOnly flag in cookie',
Xavier Guimard's avatar
Xavier Guimard committed
826
            flags         => 'hp',
827 828 829 830 831 832 833 834 835 836 837
        },
        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',
Xavier Guimard's avatar
Xavier Guimard committed
838
            flags         => 'hp',
839 840 841
        },

        # Notification
842
        oldNotifFormat => {
Xavier Guimard's avatar
Xavier Guimard committed
843 844
            type          => 'bool',
            default       => 0,
Xavier Guimard's avatar
Xavier Guimard committed
845
            documentation => 'Use old XML format for notifications',
846
        },
847 848 849 850 851
        notificationWildcard => {
            type          => 'text',
            default       => 'allusers',
            documentation => 'Notification string to match all users',
        },
Xavier Guimard's avatar
Xavier Guimard committed
852 853 854 855 856
        notificationXSLTfile => {
            type          => 'text',
            documentation => 'Custom XSLT document for notifications',
        },
        notification => {
857 858 859 860
            default       => 0,
            type          => 'bool',
            documentation => 'Notification activation',
        },
861 862 863 864 865
        notificationServer => {
            default       => 0,
            type          => 'bool',
            documentation => 'Notification server activation',
        },
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
        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 => {
884
            default       => 1,
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
            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',
        },

        # Variables
        exportedVars => {
            type          => 'keyTextContainer',
            help          => 'exportedvars.html',
            keyTest       => qr/^!?[_a-zA-Z][a-zA-Z0-9_]*$/,
Xavier Guimard's avatar
Xavier Guimard committed
904
            keyMsgFail    => '__badVariableName__',
905 906 907 908 909 910 911 912
            test          => qr/^[_a-zA-Z][a-zA-Z0-9_:\-]*$/,
            msgFail       => '__badValue__',
            default       => { 'UA' => 'HTTP_USER_AGENT' },
            documentation => 'Main exported variables',
        },
        groups => {
            type => 'keyTextContainer',
            help =>
Clément OUDOT's avatar
Clément OUDOT committed
913
              'exportedvars.html#extend_variables_using_macros_and_groups',
914 915 916 917 918 919 920
            test          => $perlExpr,
            default       => {},
            documentation => 'Groups',
        },
        macros => {
            type => 'keyTextContainer',
            help =>
Clément OUDOT's avatar
Clément OUDOT committed
921
              'exportedvars.html#extend_variables_using_macros_and_groups',
922
            keyTest       => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
Xavier Guimard's avatar
Xavier Guimard committed
923
            keyMsgFail    => '__badMacroName__',
924 925 926 927 928 929 930 931 932 933
            test          => $perlExpr,
            default       => {},
            documentation => 'Macros',
        },

        # Storage
        globalStorage => {
            type          => 'PerlModule',
            default       => 'Apache::Session::File',
            documentation => 'Session backend module',
Xavier Guimard's avatar
Xavier Guimard committed
934
            flags         => 'hp',
935 936 937 938 939 940 941
        },
        globalStorageOptions => {
            type    => 'keyTextContainer',
            default => {
                'Directory'     => '/var/lib/lemonldap-ng/sessions/',
                'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/',
                'generateModule' =>
Clément OUDOT's avatar
Clément OUDOT committed
942
                  'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
943 944
            },
            documentation => 'Session backend module options',
Xavier Guimard's avatar
Xavier Guimard committed
945
            flags         => 'hp',
946 947
        },
        localSessionStorage => {
Xavier Guimard's avatar
Xavier Guimard committed
948 949
            type          => 'PerlModule',
            default       => 'Cache::FileCache',
Xavier Guimard's avatar
Xavier Guimard committed
950
            documentation => 'Local sessions cache module',
951 952 953 954 955 956 957 958 959 960 961 962 963 964
        },
        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
Xavier Guimard's avatar
Xavier Guimard committed
965 966 967 968 969 970 971 972 973 974 975 976 977
        persistentStorage => {
            type          => 'PerlModule',
            documentation => 'Storage module for persistent sessions'
        },
        persistentStorageOptions => {
            type          => 'keyTextContainer',
            documentation => 'Options for persistent sessions storage module'
        },
        sessionDataToRemember => {
            type          => 'keyTextContainer',
            keyTest       => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
            keyMsgFail    => '__invalidSessionData__',
            documentation => 'Data to remember in login history',
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
        },

        # 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',
1000
            default       => 0,
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
            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',
        },

1014 1015 1016
        # GET issuer
        issuerDBGetActivation => {
            type          => 'bool',
1017
            default       => 0,
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
            documentation => 'Get issuer activation',
        },
        issuerDBGetPath => {
            type          => 'text',
            default       => '^/get/',
            documentation => 'Get issuer request path',
        },
        issuerDBGetRule => {
            type          => 'boolOrExpr',
            default       => 1,
            documentation => 'Get issuer rule',
        },
        issuerDBGetParameters => {
            type       => 'doubleHash',
            default    => {},
            keyTest    => qr/^$Regexp::Common::URI::RFC2396::hostname$/,
            keyMsgFail => '__badHostname__',
            test       => {
                keyTest    => qr/^(?=[^\-])[\w\-]+(?<=[^-])$/,
                keyMsgFail => '__badKeyName__',
                test       => sub {
                    my ( $val, $conf ) = @_;
1040
                    return 1
Clément OUDOT's avatar
Clément OUDOT committed
1041
                      if ( defined $conf->{macros}->{$val}
1042 1043 1044
                        or $val eq '_timezone' );
                    foreach ( keys %$conf ) {
                        return 1
Clément OUDOT's avatar
Clément OUDOT committed
1045
                          if ( $_ =~ /exportedvars$/i
1046
                            and defined $conf->{$_}->{$val} );
1047
                    }
1048
                    return ( 1, "__unknownAttrOrMacro__: $val" );
1049 1050 1051 1052 1053
                },
            },
            documentation => 'List of virtualHosts with their get parameters',
        },

1054 1055 1056 1057 1058 1059 1060
        # Password
        mailOnPasswordChange => {
            default       => 0,
            type          => 'bool',
            documentation => 'Send a mail when password is changed',
        },
        portalRequireOldPassword => {
Clément OUDOT's avatar
Clément OUDOT committed
1061 1062 1063
            default       => 1,
            type          => 'bool',
            documentation => 'Old password is required to change the password',
1064 1065 1066 1067 1068 1069 1070 1071
        },
        hideOldPassword => {
            default       => 0,
            type          => 'bool',
            documentation => 'Hide old password in portal',
        },

        # Mails
Xavier Guimard's avatar
Xavier Guimard committed
1072
        mailBody =>
Clément OUDOT's avatar
Clément OUDOT committed
1073
          { type => 'longtext', documentation => 'Custom mail body', },
1074 1075 1076 1077 1078
        mailCharset => {
            type          => 'text',
            default       => 'utf-8',
            documentation => 'Mail charset',
        },
1079 1080 1081 1082
        mailConfirmBody => {
            type          => 'longtext',
            documentation => 'Custom confirm mail body',
        },
1083 1084 1085 1086 1087 1088 1089 1090 1091
        mailConfirmSubject => {
            type          => 'text',
            documentation => 'Mail subject for reset confirmation',
        },
        mailFrom => {
            type          => 'text',
            default       => 'noreply@example.com',
            documentation => 'Sender email',
        },
Clément OUDOT's avatar
Clément OUDOT committed
1092
        mailReplyTo => { type => 'text', documentation => 'Reply-To address' },
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
        mailSessionKey => {
            type          => 'text',
            default       => 'mail',
            documentation => 'Session parameter where mail is stored',
        },
        mailSubject => {
            type          => 'text',
            documentation => 'Mail subject for new password email',
        },
        mailTimeout => {
            type          => 'int',
            default       => 0,
            documentation => 'Mail session timeout',
        },
        mailUrl => {
            type          => 'url',
1109
            default       => 'http://auth.example.com/resetpwd',
1110 1111 1112
            documentation => 'URL of password reset page',
        },
        SMTPServer => {
1113 1114
            type    => 'text',
            default => '',
Clément OUDOT's avatar
Clément OUDOT committed
1115
            test    => qr/^(?:$Regexp::Common::URI::RFC2396::host(?::\d+)?)?$/,
1116 1117
            documentation => 'SMTP Server',
        },
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
        SMTPPort => {
            type          => 'int',
            documentation => 'Fix SMTP port',
        },
        SMTPTLS => {
            type    => 'select',
            default => '',
            select  => [
                { k => '',         v => 'none' },
                { k => 'starttls', v => 'SMTP + STARTTLS' },
                { k => 'ssl',      v => 'SMTPS' },
            ],
            documentation => 'TLS protocol to use with SMTP',
        },
        SMTPTLSOpts => {
            type          => 'keyTextContainer',
            documentation => 'TLS/SSL options for SMTP',
        },
Xavier Guimard's avatar
Xavier Guimard committed
1136 1137 1138 1139 1140 1141 1142 1143
        SMTPAuthUser => {
            type          => 'text',
            documentation => 'Login to use to send mails',
        },
        SMTPAuthPass => {
            type          => 'password',
            documentation => 'Password to use to send mails',
        },
1144 1145 1146 1147 1148 1149 1150 1151 1152

        # Registration
        registerConfirmSubject => {
            type          => 'text',
            documentation => 'Mail subject for register confirmation',
        },
        registerDB => {
            type   => 'select',
            select => [
1153 1154 1155 1156 1157
                { k => 'AD',     v => 'Active Directory' },
                { k => 'Demo',   v => 'Demonstration' },
                { k => 'LDAP',   v => 'LDAP' },
                { k => 'Null',   v => 'None' },
                { k => 'Custom', v => 'customModule' },
1158
            ],
1159
            default       => 'Null',
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
            documentation => 'Register module',
        },
        registerDoneSubject => {
            type          => 'text',
            documentation => 'Mail subject when register is done',
        },
        registerTimeout => {
            default       => 0,
            type          => 'int',
            documentation => 'Register session timeout',
        },
1171 1172
        registerUrl => {
            type          => 'text',
1173
            default       => 'http://auth.example.com/register',
1174 1175
            documentation => 'URL of register page',
        },
1176

1177 1178 1179
        # Upgrade session
        upgradeSession => {
            type          => 'bool',
1180
            default       => 1,
1181 1182
            documentation => 'Upgrade session activation',
        },
1183

1184 1185 1186 1187
        # 2F
        max2FDevices => {
            default       => 10,
            type          => 'int',
1188
            documentation => 'Maximum registered 2F devices',
1189 1190 1191 1192
        },
        max2FDevicesNameLength => {
            default       => 20,
            type          => 'int',
1193
            documentation => 'Maximum 2F devices name length',
1194
        },
1195

Xavier Guimard's avatar
Xavier Guimard committed
1196 1197
        # U2F
        u2fActivation => {
Xavier Guimard's avatar
Xavier Guimard committed
1198
            type          => 'boolOrExpr',
Xavier Guimard's avatar
Xavier Guimard committed
1199 1200 1201
            default       => 0,
            documentation => 'U2F activation',
        },
1202
        u2fSelfRegistration => {
1203
            type          => 'boolOrExpr',
1204 1205
            default       => 0,
            documentation => 'U2F self registration activation',
Xavier Guimard's avatar
Xavier Guimard committed
1206
        },
Xavier Guimard's avatar
Xavier Guimard committed
1207 1208 1209
        u2fAuthnLevel => {
            type => 'int',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
1210
              'Authentication level for users authentified by password+U2F'
Xavier Guimard's avatar
Xavier Guimard committed
1211
        },
1212 1213 1214