Merge branch '2674' into 'v2.0'

2674

See merge request lemonldap-ng/lemonldap-ng!286
This commit is contained in:
Christophe Maudoux 2022-08-31 14:23:25 +00:00
commit 2f6d91c27b
40 changed files with 50 additions and 75 deletions

View File

@ -92,7 +92,4 @@
Options +FollowSymLinks Options +FollowSymLinks
DirectoryIndex index.html start.html DirectoryIndex index.html start.html
</Directory> </Directory>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -105,7 +105,4 @@
Options +FollowSymLinks Options +FollowSymLinks
DirectoryIndex index.html start.html DirectoryIndex index.html start.html
</Directory> </Directory>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -94,7 +94,4 @@
Options +FollowSymLinks Options +FollowSymLinks
DirectoryIndex index.html start.html DirectoryIndex index.html start.html
</Directory> </Directory>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -40,9 +40,6 @@ server {
#uwsgi_param SCRIPT_FILENAME $document_root$sc; #uwsgi_param SCRIPT_FILENAME $document_root$sc;
#uwsgi_param SCRIPT_NAME $sc; #uwsgi_param SCRIPT_NAME $sc;
# Uncomment this if you use https only
#add_header Strict-Transport-Security "max-age=15768000";
} }
# By default, access to this VHost is denied # By default, access to this VHost is denied

View File

@ -44,9 +44,6 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/lmerror/503
# # an upper PerlHeaderParserHandler directive # # an upper PerlHeaderParserHandler directive
# #PerlHeaderParserHandler Apache2::Const::DECLINED # #PerlHeaderParserHandler Apache2::Const::DECLINED
#</Location> #</Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -61,9 +61,6 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/lmerror/503
# # an upper PerlHeaderParserHandler directive # # an upper PerlHeaderParserHandler directive
# #PerlHeaderParserHandler Apache2::Const::DECLINED # #PerlHeaderParserHandler Apache2::Const::DECLINED
#</Location> #</Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -51,9 +51,6 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/lmerror/503
# # an upper PerlHeaderParserHandler directive # # an upper PerlHeaderParserHandler directive
# #PerlHeaderParserHandler Apache2::Const::DECLINED # #PerlHeaderParserHandler Apache2::Const::DECLINED
#</Location> #</Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -50,9 +50,6 @@ server {
# Client requests # Client requests
location / { location / {
deny all; deny all;
# Uncomment this if you use https only
#add_header Strict-Transport-Security "max-age=15768000";
} }
# Uncomment this if status is enabled # Uncomment this if status is enabled

View File

@ -95,7 +95,4 @@
Options +FollowSymLinks Options +FollowSymLinks
DirectoryIndex index.html start.html DirectoryIndex index.html start.html
</Directory> </Directory>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -114,7 +114,4 @@
Options +FollowSymLinks Options +FollowSymLinks
DirectoryIndex index.html start.html DirectoryIndex index.html start.html
</Directory> </Directory>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -98,7 +98,4 @@
Options +FollowSymLinks Options +FollowSymLinks
DirectoryIndex index.html start.html DirectoryIndex index.html start.html
</Directory> </Directory>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -35,9 +35,6 @@ server {
#uwsgi_param LLTYPE psgi; #uwsgi_param LLTYPE psgi;
#uwsgi_param SCRIPT_FILENAME $document_root$sc; #uwsgi_param SCRIPT_FILENAME $document_root$sc;
#uwsgi_param SCRIPT_NAME $sc; #uwsgi_param SCRIPT_NAME $sc;
# Uncomment this if you use https only
#add_header Strict-Transport-Security "max-age=15768000";
} }
location / { location / {

View File

@ -113,8 +113,5 @@
Header append Vary User-Agent env=!dont-vary Header append Vary User-Agent env=!dont-vary
</IfModule> </IfModule>
</Location> </Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -144,8 +144,5 @@
Header append Vary User-Agent env=!dont-vary Header append Vary User-Agent env=!dont-vary
</IfModule> </IfModule>
</Location> </Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -110,8 +110,5 @@
Header append Vary User-Agent env=!dont-vary Header append Vary User-Agent env=!dont-vary
</IfModule> </IfModule>
</Location> </Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -88,9 +88,6 @@ server {
index index.psgi; index index.psgi;
location / { location / {
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
# Uncomment this if you use https only
#add_header Strict-Transport-Security "max-age=15768000";
} }
location /static/ { location /static/ {

View File

@ -41,7 +41,4 @@ PerlModule Lemonldap::NG::Handler::ApacheMP2::Menu
<IfModule mod_dir.c> <IfModule mod_dir.c>
DirectoryIndex index.pl index.html DirectoryIndex index.pl index.html
</IfModule> </IfModule>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -41,7 +41,4 @@ PerlModule Lemonldap::NG::Handler::ApacheMP2::Menu
<IfModule mod_dir.c> <IfModule mod_dir.c>
DirectoryIndex index.pl index.html DirectoryIndex index.pl index.html
</IfModule> </IfModule>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -36,7 +36,4 @@ PerlModule Lemonldap::NG::Handler::ApacheMP2::Menu
<IfModule mod_dir.c> <IfModule mod_dir.c>
DirectoryIndex index.pl index.html DirectoryIndex index.pl index.html
</IfModule> </IfModule>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -88,9 +88,6 @@ server {
# OR in the corresponding block # OR in the corresponding block
#fastcgi_param HTTP_COOKIE $lmcookie; #fastcgi_param HTTP_COOKIE $lmcookie;
# Uncomment this if you use https only
#add_header Strict-Transport-Security "max-age=15768000";
# Set REMOTE_USER and REMOTE_CUSTOM (for FastCGI apps only) # Set REMOTE_USER and REMOTE_CUSTOM (for FastCGI apps only)
#fastcgi_param REMOTE_USER $lmremote_user; #fastcgi_param REMOTE_USER $lmremote_user;
#fastcgi_param REMOTE_CUSTOM $lmremote_custom; #fastcgi_param REMOTE_CUSTOM $lmremote_custom;

View File

@ -181,7 +181,6 @@ Nginx SSL Virtual Host example with uWSGI
#index index.psgi; #index index.psgi;
location / { location / {
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
add_header Strict-Transport-Security "max-age=15768000";
} }
} }

View File

@ -332,6 +332,7 @@ Go in Manager, ``General parameters`` » ``Advanced parameters`` »
- **Form timeout**: Form token timeout (default to 120 seconds) - **Form timeout**: Form token timeout (default to 120 seconds)
- **Use global storage**: Local cache is used by default for one time - **Use global storage**: Local cache is used by default for one time
tokens. To use global storage, set it to 'On' tokens. To use global storage, set it to 'On'
- **Strict-Transport-Security Max-age**: set STS header max-age if you use SSL only (by example: 15768000)
- **CrowdSec Bouncer**: set to 'On' to enable :doc:`CrowdSec Bouncer plugin<crowdsec>` - **CrowdSec Bouncer**: set to 'On' to enable :doc:`CrowdSec Bouncer plugin<crowdsec>`
- **Brute-Force Attack protection**: set to 'On' to enable :doc:`Brute-force protection plugin<bruteforceprotection>` - **Brute-Force Attack protection**: set to 'On' to enable :doc:`Brute-force protection plugin<bruteforceprotection>`
- **LWP::UserAgent and SSL options**: insert here options to pass to - **LWP::UserAgent and SSL options**: insert here options to pass to

View File

@ -4259,6 +4259,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => 0, 'default' => 0,
'type' => 'bool' 'type' => 'bool'
}, },
'strictTransportSecurityMax_Age' => {
'type' => 'text'
},
'successLoginNumber' => { 'successLoginNumber' => {
'default' => 5, 'default' => 5,
'type' => 'int' 'type' => 'int'

View File

@ -1093,7 +1093,11 @@ sub attributes {
corsMax_Age => { corsMax_Age => {
type => 'text', type => 'text',
default => '86400', # 24 hours default => '86400', # 24 hours
documentation => 'MAx-age for Cross-Origin Resource Sharing', documentation => 'Max-age for Cross-Origin Resource Sharing',
},
strictTransportSecurityMax_Age => {
type => 'text',
documentation => 'Max-age for Strict-Transport-Security',
}, },
cspDefault => { cspDefault => {
type => 'text', type => 'text',

View File

@ -1092,6 +1092,7 @@ sub tree {
'requireToken', 'requireToken',
'formTimeout', 'formTimeout',
'tokenUseGlobalStorage', 'tokenUseGlobalStorage',
'strictTransportSecurityMax_Age',
{ {
title => 'CrowdSecPlugin', title => 'CrowdSecPlugin',
help => 'crowdsec.html', help => 'crowdsec.html',

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Expiration time", "stayConnectedTimeout":"Expiration time",
"storePassword":"تخزين كلمة مرور المستخدم في بيانات الجلسة", "storePassword":"تخزين كلمة مرور المستخدم في بيانات الجلسة",
"string":"String", "string":"String",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Subtitle", "subtitle":"Subtitle",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"تم الحفظ بنجاح", "successfullySaved":"تم الحفظ بنجاح",

View File

@ -1133,6 +1133,7 @@
"stayConnectedCookieName":"Cookie name", "stayConnectedCookieName":"Cookie name",
"stayConnectedTimeout":"Expiration time", "stayConnectedTimeout":"Expiration time",
"storePassword":"Store user password in session", "storePassword":"Store user password in session",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"string":"String", "string":"String",
"subtitle":"Subtitle", "subtitle":"Subtitle",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Expiration time", "stayConnectedTimeout":"Expiration time",
"storePassword":"Almacenar contraseña de usuario en la sesión", "storePassword":"Almacenar contraseña de usuario en la sesión",
"string":"String", "string":"String",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Subtítulo", "subtitle":"Subtítulo",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"Salvado con éxito", "successfullySaved":"Salvado con éxito",

View File

@ -2,7 +2,7 @@
"2faSessions":"Explorateur sessions 2ndFA", "2faSessions":"Explorateur sessions 2ndFA",
"2ndFA":"Seconds Facteurs", "2ndFA":"Seconds Facteurs",
"ADPwdExpireWarning":"Avertissement avant expiration du mot de passe", "ADPwdExpireWarning":"Avertissement avant expiration du mot de passe",
"ADPwdMaxAge":"Âge maximal du mot de passe", "ADPwdMaxAge":"Age maximal du mot de passe",
"AuthLDAPFilter":"Filtre d'authentification", "AuthLDAPFilter":"Filtre d'authentification",
"Configuration":"Configuration", "Configuration":"Configuration",
"CrowdSecPlugin":"CrowdSec Bouncer", "CrowdSecPlugin":"CrowdSec Bouncer",
@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Durée de validité", "stayConnectedTimeout":"Durée de validité",
"storePassword":"Stocke le mot de passe de l'utilisateur en session", "storePassword":"Stocke le mot de passe de l'utilisateur en session",
"string":"Chaîne", "string":"Chaîne",
"strictTransportSecurityMax_Age":"Age maximum Strict-Transport-Security",
"subtitle":"Sous-titre", "subtitle":"Sous-titre",
"successLoginNumber":"Nombre de connexions mémorisées", "successLoginNumber":"Nombre de connexions mémorisées",
"successfullySaved":"Sauvegarde effectuée", "successfullySaved":"Sauvegarde effectuée",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Expiration time", "stayConnectedTimeout":"Expiration time",
"storePassword":"Store user password in session", "storePassword":"Store user password in session",
"string":"String", "string":"String",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Subtitle", "subtitle":"Subtitle",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"נשמר בהצלחה", "successfullySaved":"נשמר בהצלחה",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Expiration time", "stayConnectedTimeout":"Expiration time",
"storePassword":"Memorizzare la password dell'utente nei dati di sessione", "storePassword":"Memorizzare la password dell'utente nei dati di sessione",
"string":"String", "string":"String",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Subtitle", "subtitle":"Subtitle",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"Salvato con successo", "successfullySaved":"Salvato con successo",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Data ważności", "stayConnectedTimeout":"Data ważności",
"storePassword":"Przechowuj hasło użytkownika w sesji", "storePassword":"Przechowuj hasło użytkownika w sesji",
"string":"Łańcuch znaków", "string":"Łańcuch znaków",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Podtytuł", "subtitle":"Podtytuł",
"successLoginNumber":"Maksymalna liczba udanych logowań", "successLoginNumber":"Maksymalna liczba udanych logowań",
"successfullySaved":"Pomyślnie zapisano", "successfullySaved":"Pomyślnie zapisano",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Son kullanma süresi", "stayConnectedTimeout":"Son kullanma süresi",
"storePassword":"Kullanıcı parolasını oturumda sakla", "storePassword":"Kullanıcı parolasını oturumda sakla",
"string":"Dize", "string":"Dize",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Altyazı", "subtitle":"Altyazı",
"successLoginNumber":"Maksimum başarılı giriş sayısı", "successLoginNumber":"Maksimum başarılı giriş sayısı",
"successfullySaved":"Başarıyla kaydedildi", "successfullySaved":"Başarıyla kaydedildi",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"Expiration time", "stayConnectedTimeout":"Expiration time",
"storePassword":"Lưu trữ mật khẩu người dùng trong các dữ liệu phiên", "storePassword":"Lưu trữ mật khẩu người dùng trong các dữ liệu phiên",
"string":"String", "string":"String",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"Subtitle", "subtitle":"Subtitle",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"Lưu thành công", "successfullySaved":"Lưu thành công",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"過期名稱", "stayConnectedTimeout":"過期名稱",
"storePassword":"在工作階段中儲存使用者密碼", "storePassword":"在工作階段中儲存使用者密碼",
"string":"字串", "string":"字串",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"副標題", "subtitle":"副標題",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"成功儲存", "successfullySaved":"成功儲存",

View File

@ -1134,6 +1134,7 @@
"stayConnectedTimeout":"過期名稱", "stayConnectedTimeout":"過期名稱",
"storePassword":"在工作階段中儲存使用者密碼", "storePassword":"在工作階段中儲存使用者密碼",
"string":"字串", "string":"字串",
"strictTransportSecurityMax_Age":"Strict-Transport-Security max age",
"subtitle":"副標題", "subtitle":"副標題",
"successLoginNumber":"Max successful logins count", "successLoginNumber":"Max successful logins count",
"successfullySaved":"成功儲存", "successfullySaved":"成功儲存",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -946,21 +946,32 @@ sub sendHtml {
$self->setCorsHeaderFromConfig($res); $self->setCorsHeaderFromConfig($res);
if ( $self->conf->{strictTransportSecurityMax_Age}
and $self->conf->{portal} =~ /^https:/ )
{
push @{ $res->[1] },
'Strict-Transport-Security' =>
"max-age=$self->{conf}->{strictTransportSecurityMax_Age}";
$self->logger->debug(
"Set Strict-Transport-Security with: $self->{conf}->{strictTransportSecurityMax_Age}"
);
}
# Set authorized URL for POST # Set authorized URL for POST
my $csp = $self->csp . "form-action " . $self->conf->{cspFormAction}; my $csp = $self->csp . "form-action " . $self->conf->{cspFormAction};
if ( my $url = $req->urldc ) { if ( my $url = $req->urldc ) {
$self->logger->debug("Required urldc : $url"); $self->logger->debug("Required urldc: $url");
$url =~ URIRE; $url =~ URIRE;
$url = $2 . '://' . $3 . ( $4 ? ":$4" : '' ); $url = $2 . '://' . $3 . ( $4 ? ":$4" : '' );
$self->logger->debug("Set CSP form-action with urldc : $url"); $self->logger->debug("Set CSP form-action with urldc: $url");
$csp .= " $url"; $csp .= " $url";
} }
my $url = $args{params}->{URL}; my $url = $args{params}->{URL};
if ( defined $url ) { if ( defined $url ) {
$self->logger->debug("Required Params URL : $url"); $self->logger->debug("Required Params URL: $url");
if ( $url =~ URIRE ) { if ( $url =~ URIRE ) {
$url = $2 . '://' . $3 . ( $4 ? ":$4" : '' ); $url = $2 . '://' . $3 . ( $4 ? ":$4" : '' );
$self->logger->debug("Set CSP form-action with Params URL : $url"); $self->logger->debug("Set CSP form-action with Params URL: $url");
$csp .= " $url"; $csp .= " $url";
} }
} }
@ -1018,7 +1029,7 @@ sub sendHtml {
# Set CSP header # Set CSP header
push @{ $res->[1] }, 'Content-Security-Policy' => $csp; push @{ $res->[1] }, 'Content-Security-Policy' => $csp;
$self->logger->debug("Apply following CSP : $csp"); $self->logger->debug("Apply following CSP: $csp");
return $res; return $res;
} }
@ -1259,7 +1270,7 @@ sub setCorsHeaderFromConfig {
if ( $self->conf->{corsEnabled} ) { if ( $self->conf->{corsEnabled} ) {
my @cors = split /;/, $self->cors; my @cors = split /;/, $self->cors;
push @{ $response->[1] }, @cors; push @{ $response->[1] }, @cors;
$self->logger->debug('Apply following CORS policy :'); $self->logger->debug('Apply following CORS policy:');
$self->logger->debug(" $_") for @cors; $self->logger->debug(" $_") for @cors;
} }
} }

View File

@ -11,9 +11,11 @@ my $res;
my $client = LLNG::Manager::Test->new( { my $client = LLNG::Manager::Test->new( {
ini => { ini => {
logLevel => 'error', logLevel => 'error',
useSafeJail => 1, portal => 'https://auth.example.com/',
portalFavicon => 'common/llng.ico' useSafeJail => 1,
strictTransportSecurityMax_Age => '1977',
portalFavicon => 'common/llng.ico'
} }
} }
); );
@ -33,6 +35,9 @@ ok(
), ),
'Get Menu' 'Get Menu'
); );
ok( getHeader( $res, 'Strict-Transport-Security' ) =~ /^max-age=1977$/,
'Strict-Transport-Security is set' )
or explain( $res->[1], 'Content-Type => application/xml' );
ok( $res->[2]->[0] =~ /<span trmsg="37">/, 'Rejected with PE_BADURL' ) ok( $res->[2]->[0] =~ /<span trmsg="37">/, 'Rejected with PE_BADURL' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ m%<span id="languages"></span>%, ' Language icons found' ) ok( $res->[2]->[0] =~ m%<span id="languages"></span>%, ' Language icons found' )
@ -40,7 +45,7 @@ ok( $res->[2]->[0] =~ m%<span id="languages"></span>%, ' Language icons found' )
ok( $res->[2]->[0] =~ m%link href="/static/common/llng.ico%, ok( $res->[2]->[0] =~ m%link href="/static/common/llng.ico%,
' Custom favicon found' ) ' Custom favicon found' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(4); count(5);
# Test "first access" with a wildcard-protected url # Test "first access" with a wildcard-protected url
ok( ok(