Attributes.pm 117 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;

Xavier Guimard's avatar
Xavier Guimard committed
9
our $VERSION = '2.0.2';
10 11 12
use strict;
use Regexp::Common qw/URI/;

Christophe Maudoux's avatar
Christophe Maudoux committed
13

14
my $perlExpr = sub {
15
    my ( $val, $conf ) = @_;
16
    my $s = '';
17
    Safe->new->reval("BEGIN { warnings->unimport; } $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
        portalStatus => {
            type          => 'bool',
            default       => 0,
Xavier Guimard's avatar
Typo  
Xavier Guimard committed
353
            help          => 'status.html',
354 355
            documentation => 'Enable portal status',
        },
356 357 358 359
        portalUserAttr => {
            type    => 'text',
            default => '_user',
            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
            default       => 'get',
            documentation => 'HTTP method for redirect page form',
        },
369 370 371 372 373 374
        reloadTimeout => {
            type          => 'int',
            default       => 5,
            documentation => 'Configuration reload timeout',
            flags         => 'm',
        },
375
        reloadUrls => {
Clément OUDOT's avatar
Clément OUDOT committed
376 377 378 379 380
            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
381
            documentation => 'URL to call on reload',
382
        },
Clément OUDOT's avatar
Clément OUDOT committed
383
        portalMainLogo => {
384 385 386 387
            type          => 'text',
            default       => 'common/logos/logo_llng_400px.png',
            documentation => 'Portal main logo path',
        },
388 389 390 391 392
        showLanguages => {
            type          => 'bool',
            default       => 1,
            documentation => 'Display langs icons',
        },
393 394 395 396
        staticPrefix => {
            type          => 'text',
            documentation => 'Prefix of static files for HTML templates',
        },
397 398 399 400
        multiValuesSeparator => {
            type          => 'authParamsText',
            default       => '; ',
            documentation => 'Separator for multiple values',
Xavier Guimard's avatar
Xavier Guimard committed
401
            flags         => 'hmp',
402
        },
Xavier Guimard's avatar
Xavier Guimard committed
403
        stayConnected => {
Xavier Guimard's avatar
Typo  
Xavier Guimard committed
404 405
            type => 'bool',

406
            #help          => 'stayconnected.html',
407
            default       => 0,
Xavier Guimard's avatar
Xavier Guimard committed
408 409
            documentation => 'Enable StayConnected plugin',
        },
410
        checkState => {
411
            type          => 'bool',
412
            default       => 0,
413 414
            documentation => 'Enable CheckState plugin',
        },
415
        checkStateSecret => {
416
            type          => 'text',
417 418
            documentation => 'Secret token for CheckState plugin',
        },
419
        skipRenewConfirmation => {
420 421
            type    => 'bool',
            default => 0,
422
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
423
              'Avoid asking confirmation when an Issuer asks to renew auth',
424
        },
425 426 427 428
        handlerInternalCache => {
            type          => 'int',
            default       => 15,
            documentation => 'Handler internal cache timeout',
Christophe Maudoux's avatar
Christophe Maudoux committed
429
            flags         => 'hp',
430
        },
431

432 433 434 435 436 437 438 439 440
        # Loggers (ini only)
        logLevel => {
            type          => 'text',
            documentation => 'Log level, must be set in .ini',
            flags         => 'hmp',
        },
        logger => {
            type          => 'text',
            documentation => 'technical logger',
Xavier Guimard's avatar
Xavier Guimard committed
441
            flags         => 'hmp',
442 443 444 445
        },
        userLogger => {
            type          => 'text',
            documentation => 'User actions logger',
Xavier Guimard's avatar
Xavier Guimard committed
446
            flags         => 'hmp',
447 448 449 450
        },
        log4perlConfFile => {
            type          => 'text',
            documentation => 'Log4Perl logger configuration file',
Xavier Guimard's avatar
Xavier Guimard committed
451
            flags         => 'hmp',
452 453 454 455
        },
        sentryDsn => {
            type          => 'text',
            documentation => 'Sentry logger DSN',
Xavier Guimard's avatar
Xavier Guimard committed
456
            flags         => 'hmp',
457 458 459 460
        },
        syslogFacility => {
            type          => 'text',
            documentation => 'Syslog logger technical facility',
Xavier Guimard's avatar
Xavier Guimard committed
461
            flags         => 'hmp',
462 463 464 465
        },
        userSyslogFacility => {
            type          => 'text',
            documentation => 'Syslog logger user-actions facility',
Xavier Guimard's avatar
Xavier Guimard committed
466
            flags         => 'hmp',
467 468 469
        },

        # Manager or PSGI protected apps
470
        protection => {
Clément OUDOT's avatar
Clément OUDOT committed
471 472 473
            type          => 'text',
            test          => qr/^(?:none|authenticate|manager|)$/,
            msgFail       => '__authorizedValues__: none authenticate manager',
474
            documentation => 'Manager protection method',
Xavier Guimard's avatar
Xavier Guimard committed
475
            flags         => 'hm',
476 477 478 479 480 481 482 483 484 485
        },

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

        # Security
560
        formTimeout => {
Xavier Guimard's avatar
Xavier Guimard committed
561 562
            default       => 120,
            type          => 'int',
563 564 565
            documentation => 'Token timeout for forms',
        },
        requireToken => {
Xavier Guimard's avatar
Xavier Guimard committed
566 567
            default       => 1,
            type          => 'bool',
568 569
            documentation => 'Enable token for forms',
        },
570 571 572 573 574
        tokenUseGlobalStorage => {
            default       => 0,
            type          => 'bool',
            documentation => 'Enable global token storage',
        },
575 576 577 578
        cda => {
            default       => 0,
            type          => 'bool',
            documentation => 'Enable Cross Domain Authentication',
Xavier Guimard's avatar
Xavier Guimard committed
579
            flags         => 'hp',
580 581 582 583 584 585
        },
        checkXSS => {
            default       => 1,
            type          => 'bool',
            documentation => 'Check XSS',
        },
586
        portalForceAuthn => {
587
            default => 0,
588
            help    => 'forcereauthn.html',
589 590
            type    => 'bool',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
591
              'Enable force to authenticate when displaying portal',
592
        },
593 594
        portalForceAuthnInterval => {
            default => 5,
595 596
            type    => 'int',
            documentation =>
Xavier Guimard's avatar
Typo  
Xavier Guimard committed
597
'Maximum interval in seconds since last authentication to force reauthentication',
598
        },
599
        bruteForceProtection => {
600
            default       => 0,
601
            help          => 'bruteforceprotection.html',
602 603 604 605 606 607 608
            type          => 'bool',
            documentation => 'Enable brute force attack protection',
        },
        bruteForceProtectionTempo => {
            default => 30,
            type    => 'int',
            documentation =>
Clément OUDOT's avatar
Clément OUDOT committed
609
              'Brute force attack protection -> Tempo before try again',
610 611 612 613 614
        },
        bruteForceProtectionMaxAge => {
            default => 300,
            type    => 'int',
            documentation =>
615 616 617 618 619 620 621
              'Brute force attack protection -> Max age between last and first allowed failed login',
        },
        bruteForceProtectionMaxFailed => {
            default => 3,
            type    => 'int',
            documentation =>
              'Brute force attack protection -> Max allowed failed login',
622
        },
623
        grantSessionRules => {
Xavier Guimard's avatar
Xavier Guimard committed
624 625
            type          => 'grantContainer',
            keyTest       => $perlExpr,
Clément OUDOT's avatar
Clément OUDOT committed
626
            test          => sub { 1 },
Xavier Guimard's avatar
Xavier Guimard committed
627
            documentation => 'Rules to grant sessions',
628 629 630 631 632 633 634 635 636 637
        },
        hiddenAttributes => {
            type          => 'text',
            default       => '_password',
            documentation => 'Name of attributes to hide in logs',
        },
        key => {
            type          => 'password',
            documentation => 'Secret key',
        },
638 639
        cspDefault => {
            type          => 'text',
Xavier Guimard's avatar
Xavier Guimard committed
640
            default       => "'self'",
641 642
            documentation => 'Default value for Content-Security-Policy',
        },
643
        cspFormAction => {
644 645 646 647
            type    => 'text',
            default => "'self'",
            documentation =>
              'Form action destination for Content-Security-Policy',
648
        },
649 650
        cspImg => {
            type          => 'text',
651
            default       => "'self' data:",
652 653 654 655 656 657 658 659 660
            documentation => 'Image source for Content-Security-Policy',
        },
        cspScript => {
            type          => 'text',
            default       => "'self'",
            documentation => 'Javascript source for Content-Security-Policy',
        },
        cspStyle => {
            type          => 'text',
661
            default       => "'self'",
662 663 664 665 666 667
            documentation => 'Style source for Content-Security-Policy',
        },
        cspConnect => {
            type    => 'text',
            default => "'self'",
            documentation =>
Christophe Maudoux's avatar
Typo  
Christophe Maudoux committed
668
              'Authorized Ajax destination for Content-Security-Policy',
669 670 671 672 673 674
        },
        cspFont => {
            type          => 'text',
            default       => "'self'",
            documentation => 'Font source for Content-Security-Policy',
        },
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
        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
690
        trustedDomains =>
Clément OUDOT's avatar
Clément OUDOT committed
691
          { type => 'text', documentation => 'Trusted domains', },
Xavier Guimard's avatar
Xavier Guimard committed
692
        storePassword => {
693 694 695 696 697 698
            default       => 0,
            type          => 'bool',
            documentation => 'Store password in session',
        },
        timeout => {
            type          => 'int',
Xavier Guimard's avatar
Xavier Guimard committed
699
            test          => sub { $_[0] > 0 },
700 701 702 703
            default       => 72000,
            documentation => 'Session timeout on server side',
        },
        timeoutActivity => {
704
            type          => 'int',
Xavier Guimard's avatar
Xavier Guimard committed
705
            test          => sub { $_[0] >= 0 },
706 707 708
            default       => 0,
            documentation => 'Session activity timeout on server side',
        },
709 710 711 712 713 714
        timeoutActivityInterval => {
            type          => 'int',
            test          => sub { $_[0] >= 0 },
            default       => 60,
            documentation => 'Update session timeout interval on server side',
        },
715 716 717 718 719 720 721 722 723 724 725 726 727 728
        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
729
            flags         => 'h',
730 731 732 733 734 735 736 737 738
        },
        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
739
            help          => 'safejail.html',
740
            documentation => 'Activate Safe jail',
Xavier Guimard's avatar
Xavier Guimard committed
741
            flags         => 'hp',
742 743 744 745 746
        },
        whatToTrace => {
            type          => 'lmAttrOrMacro',
            default       => 'uid',
            documentation => 'Session parameter used to fill REMOTE_USER',
Xavier Guimard's avatar
Xavier Guimard committed
747
            flags         => 'hp',
748
        },
749
        lwpOpts => {
Xavier Guimard's avatar
Xavier Guimard committed
750 751 752
            type          => 'keyTextContainer',
            documentation => 'Options given to LWP::UserAgent',
        },
753 754 755 756
        lwpSslOpts => {
            type          => 'keyTextContainer',
            documentation => 'SSL options given to LWP::UserAgent',
        },
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 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801

        # 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 => {
Xavier Guimard's avatar
Xavier Guimard committed
802
            default       => 0,
803 804 805
            type          => 'bool',
            documentation => 'Display reset password button in portal',
        },
806
        passwordResetAllowedRetries => {
Christophe Maudoux's avatar
Christophe Maudoux committed
807
            default       => 3,
808 809 810
            type          => 'int',
            documentation => 'Maximum number of retries to reset password',
        },
811 812
        portalDisplayOidcConsents => {
            type          => 'boolOrExpr',
813
            default       => '$_oidcConnectedRP',
814 815
            documentation => 'Display OIDC consent tab in portal',
        },
816 817

        # Cookies
Xavier Guimard's avatar
Xavier Guimard committed
818
        cookieExpiration => {
819
            type          => 'int',
Xavier Guimard's avatar
Xavier Guimard committed
820 821 822
            documentation => 'Cookie expiration',
            flags         => 'hp',
        },
Xavier Guimard's avatar
Xavier Guimard committed
823
        cookieName => {
824 825 826 827 828
            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
829
            flags         => 'hp',
830 831
        },
        domain => {
Clément OUDOT's avatar
Clément OUDOT committed
832 833 834 835
            type          => 'text',
            test          => qr/^(?:$Regexp::Common::URI::RFC2396::hostname)?$/,
            msgFail       => '__badDomainName__',
            default       => 'example.com',
836
            documentation => 'DNS domain',
Xavier Guimard's avatar
Xavier Guimard committed
837
            flags         => 'hp',
838 839 840 841 842
        },
        httpOnly => {
            default       => 1,
            type          => 'bool',
            documentation => 'Enable httpOnly flag in cookie',
Xavier Guimard's avatar
Xavier Guimard committed
843
            flags         => 'hp',
844 845 846 847 848 849 850 851 852 853 854
        },
        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
855
            flags         => 'hp',
856 857 858
        },

        # Notification
859
        oldNotifFormat => {
Xavier Guimard's avatar
Xavier Guimard committed
860 861
            type          => 'bool',
            default       => 0,
Xavier Guimard's avatar
Xavier Guimard committed
862
            documentation => 'Use old XML format for notifications',
863
        },
864 865 866 867 868
        notificationWildcard => {
            type          => 'text',
            default       => 'allusers',
            documentation => 'Notification string to match all users',
        },
Xavier Guimard's avatar
Xavier Guimard committed
869 870 871 872 873
        notificationXSLTfile => {
            type          => 'text',
            documentation => 'Custom XSLT document for notifications',
        },
        notification => {
874 875 876 877
            default       => 0,
            type          => 'bool',
            documentation => 'Notification activation',
        },
878 879 880 881 882
        notificationServer => {
            default       => 0,
            type          => 'bool',
            documentation => 'Notification server activation',
        },
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
        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 => {
901
            default       => 1,
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
            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
921
            keyMsgFail    => '__badVariableName__',
922 923 924 925 926 927 928 929
            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
930
              'exportedvars.html#extend_variables_using_macros_and_groups',
931 932 933 934 935 936 937
            test          => $perlExpr,
            default       => {},
            documentation => 'Groups',
        },
        macros => {
            type => 'keyTextContainer',
            help =>
Clément OUDOT's avatar
Clément OUDOT committed
938
              'exportedvars.html#extend_variables_using_macros_and_groups',
939
            keyTest       => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
Xavier Guimard's avatar
Xavier Guimard committed
940
            keyMsgFail    => '__badMacroName__',
941 942 943 944 945 946 947 948 949 950
            test          => $perlExpr,
            default       => {},
            documentation => 'Macros',
        },

        # Storage
        globalStorage => {
            type          => 'PerlModule',
            default       => 'Apache::Session::File',
            documentation => 'Session backend module',
Xavier Guimard's avatar
Xavier Guimard committed
951
            flags         => 'hp',
952 953 954 955 956 957 958
        },
        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
959
                  'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
960 961
            },
            documentation => 'Session backend module options',
Xavier Guimard's avatar
Xavier Guimard committed
962
            flags         => 'hp',
963 964
        },
        localSessionStorage => {
Xavier Guimard's avatar
Xavier Guimard committed
965 966
            type          => 'PerlModule',
            default       => 'Cache::FileCache',
Xavier Guimard's avatar
Xavier Guimard committed
967
            documentation => 'Local sessions cache module',
968 969 970 971 972 973 974 975 976 977 978 979 980 981
        },
        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
982 983 984 985 986 987 988 989 990 991 992 993 994
        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',
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
        },

        # 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',
1017
            default       => 0,
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
            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',
        },

1031 1032 1033
        # GET issuer
        issuerDBGetActivation => {
            type          => 'bool',
1034
            default       => 0,
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
            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 ) = @_;
1057
                    return 1
Clément OUDOT's avatar
Clément OUDOT committed
1058
                      if ( defined $conf->{macros}->{$val}
1059 1060 1061
                        or $val eq '_timezone' );
                    foreach ( keys %$conf ) {
                        return 1
Clément OUDOT's avatar
Clément OUDOT committed
1062