From 7b55ad05ae37c44e1ecdb4220ded079e0e70d4bc Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Wed, 6 Apr 2022 22:47:09 +0200 Subject: [PATCH 01/35] Harmonize DevOps doc --- doc/sources/admin/ssoaas.rst | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/doc/sources/admin/ssoaas.rst b/doc/sources/admin/ssoaas.rst index 3e98f0129..ae0acf2ca 100644 --- a/doc/sources/admin/ssoaas.rst +++ b/doc/sources/admin/ssoaas.rst @@ -93,12 +93,12 @@ You can use 'uwsgi_param' directive for requesting a Central uWSGI server (Nginx fastcgi_pass_request_body off; fastcgi_param CONTENT_LENGTH ""; - # Keep original hostname - fastcgi_param HOST $http_host; - # Keep original request (LL::NG server will receive /lmauth) fastcgi_param X_ORIGINAL_URI $original_uri; + # Keep original hostname + fastcgi_param HOST $http_host; + # Set redirection parameters fastcgi_param HTTPS_REDIRECT "$https"; fastcgi_param PORT_REDIRECT $server_port; @@ -150,11 +150,11 @@ You can use 'uwsgi_param' directive for requesting a Central uWSGI server (Nginx Apache ^^^^^^ -LL::NG provides an experimental FastCGI client. You have to +LL::NG provides a dedicated FastCGI client. You have to install LemonLDAP::NG handler (LL::NG FastCGI client), FCGI::Client (Perl FastCGI dependency) and Mod_Perl2 (Apache module) used for parsing HTTP headers. -Then, add this in your apache2.conf web applications or reverse-proxies. +Then, add this in your apache2.conf web applications or ReverseProxies. .. code-block:: apache @@ -182,17 +182,16 @@ Then, add this in your apache2.conf web applications or reverse-proxies. # Keep original hostname PerlSetVar HOST HTTP_HOST - # This URL will be fetched by the Central FastCGI server then - # used for compliling access rules and headers about this VirtualHost - # CHECK THAT IT CAN BE REACHED BY THE CENTRAL FASTCGI SERVER - # PerlSetVar RULES_URL http://rulesserver/my.json - PerlSetVar RULES_URL http://myapp.domain.com/rules.json - # Set redirection parameters PerlSetVar PORT_REDIRECT SERVER_PORT PerlSetVar HTTPS_REDIRECT HTTPS - + # This URL will be fetched by the Central FastCGI server every 10 mn and + # then used for compliling access rules and headers relative to this VirtualHost + # CHECK THAT IT CAN BE REACHED BY THE CENTRAL FASTCGI SERVER + # PerlSetVar RULES_URL http://rulesserver/my.json + PerlSetVar RULES_URL http://myapp.domain.com/rules.json + Node.js @@ -200,7 +199,7 @@ Node.js Using `express `__ and `fastcgi-authz-client `__, -you can protect also an Express server. Example: +you can also protect an Express server. Example: .. code-block:: javascript @@ -259,7 +258,7 @@ Simple example: host => '127.0.0.1', port => '9090', fcgi_auth_params => { - RULES_URL => 'https://my-server/my.json', + RULES_URL => 'https://my-server/rules.json', HTTPS_REDIRECT => 'ON', PORT_REDIRECT => 443 }, @@ -293,31 +292,40 @@ directory. internal; include /etc/nginx/fastcgi_params; fastcgi_pass unix:/var/run/llng-fastcgi-server/llng-fastcgi.sock; + # Force handler type: fastcgi_param VHOSTTYPE DevOps; + # Drop post datas fastcgi_pass_request_body off; fastcgi_param CONTENT_LENGTH ""; + # Keep original hostname fastcgi_param HOST $http_host; + # Keep original request (LL::NG server will received /lmauth) fastcgi_param X_ORIGINAL_URI $original_uri; + # Set redirection params fastcgi_param HTTPS_REDIRECT "$https"; fastcgi_param PORT_REDIRECT $server_port; } + location /rules.json { auth_request off; allow 127.0.0.0/8; deny all; } + location / { auth_request /lmauth; set $original_uri $uri$is_args$args; auth_request_set $lmremote_user $upstream_http_lm_remote_user; auth_request_set $lmlocation $upstream_http_location; error_page 401 $lmlocation; + include /etc/nginx/nginx-lua-headers.conf; + proxy_pass https://$vhost.internal.domain; } } From 25631100975b716e3d448b391b8902f01c43660b Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Wed, 6 Apr 2022 22:59:05 +0200 Subject: [PATCH 02/35] Typos --- doc/sources/admin/ssoaas.rst | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/sources/admin/ssoaas.rst b/doc/sources/admin/ssoaas.rst index ae0acf2ca..bac5d1414 100644 --- a/doc/sources/admin/ssoaas.rst +++ b/doc/sources/admin/ssoaas.rst @@ -22,22 +22,22 @@ user attributes to an application ``*aaS`` means that application can drive underlying layer (IaaS for infrastructure, PaaS for platform,…). So for us, ``SSOaaS`` must provide the ability for an application to manage authorizations and choose user -attributes to set. Authentication can not be really ``*aaS``: application -must just use it but not manage it. +attributes to receive. Authentication can not be really ``*aaS``: application +can just use it but not manage it. LL::NG affords some features that can be used for providing SSO as a service. So a web application can manage its rules and headers. Docker or VM images (Nginx only) includes LL::NG Nginx configuration that aims to a -:ref:`central LL::NG authorization server`. +:ref:`Central LL::NG authorization server`. By default, all authenticated users can access and just one header is set: ``Auth-User``. If application defines a ``RULES_URL`` parameter that refers to a JSON file, authorization server will read it, apply specified rules and set required headers (see :doc:`DevOps Handler`). -Two different kind of architecture are existing to do this: +Two different kinds of architecture are existing to do this: -- Using a :doc:`central FastCGI (or uWSGI) server` +- Using a :doc:`Central FastCGI (or uWSGI) server` - Using front Reverse-Proxies *(some cloud or HA installations use reverse-proxies in front-end)* @@ -52,7 +52,7 @@ Two different kind of architecture are existing to do this: ```route-remote-addr = ^127\.0\.0\.25[34]$ break: 403 Forbidden for IP ${REMOTE_ADDR}``` -Example of a central FastCGI architecture: +Example of a Central FastCGI architecture: |image0| @@ -69,7 +69,8 @@ Nginx Examples below are customized web server templates for requesting authorization from a Central FastCGI server. -You can use 'uwsgi_param' directive for requesting a Central uWSGI server (Nginx only): +You can replace 'fastcgi_*' directives by 'uwsgi_*' for +requesting a Central uWSGI server (Nginx only): .. code-block:: nginx @@ -130,7 +131,7 @@ You can use 'uwsgi_param' directive for requesting a Central uWSGI server (Nginx fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; } - # Example as ReverseProxy: + # Example as Reverse-Proxy: location /api/ { auth_request /lmauth; set $original_uri $uri$is_args$args; @@ -147,14 +148,15 @@ You can use 'uwsgi_param' directive for requesting a Central uWSGI server (Nginx } } + Apache ^^^^^^ LL::NG provides a dedicated FastCGI client. You have to install LemonLDAP::NG handler (LL::NG FastCGI client), -FCGI::Client (Perl FastCGI dependency) and Mod_Perl2 (Apache module) -used for parsing HTTP headers. -Then, add this in your apache2.conf web applications or ReverseProxies. +FCGI::Client (Perl FastCGI dependency) and Mod_Perl2 (Apache module +used for parsing HTTP headers). +Then, add this in your apache2.conf web applications or Reverse-Proxies. .. code-block:: apache @@ -194,6 +196,7 @@ Then, add this in your apache2.conf web applications or ReverseProxies. + Node.js ^^^^^^^ @@ -228,6 +231,7 @@ you can also protect an Express server. Example: return console.log('Example app listening on port 3000!'); }); + Plack application ^^^^^^^^^^^^^^^^^ @@ -325,7 +329,7 @@ directory. error_page 401 $lmlocation; include /etc/nginx/nginx-lua-headers.conf; - + proxy_pass https://$vhost.internal.domain; } } From 89e389998dcb8ad7d8d63e87c512498c9e1cd19e Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Thu, 7 Apr 2022 22:39:19 +0200 Subject: [PATCH 03/35] Pass SSL options to DevOps Handler UA --- .../lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm | 24 +++++++++---------- .../lib/Lemonldap/NG/Handler/Lib/DevOps.pm | 11 ++++++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm index c2b9b6eda..576f9e067 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/AuthBasic.pm @@ -11,12 +11,23 @@ use Lemonldap::NG::Common::UserAgent; use Lemonldap::NG::Common::FormEncode; use Lemonldap::NG::Common::Session; -our $VERSION = '2.0.7'; +our $VERSION = '2.0.15'; our @ISA = ('Exporter'); our @EXPORT = qw(fetchId retrieveSession createSession hideCookie goToPortal); our @EXPORT_OK = @EXPORT; our $_ua; +sub ua { + my ($class) = @_; + return $_ua if $_ua; + $_ua = Lemonldap::NG::Common::UserAgent->new( { + lwpOpts => $class->tsv->{lwpOpts}, + lwpSslOpts => $class->tsv->{lwpSslOpts} + } + ); + return $_ua; +} + ## @rmethod protected fetchId # Get user session id from Authorization header # Unlike usual processing, session id is computed from user creds, @@ -163,15 +174,4 @@ sub goToPortal { } } -sub ua { - my ($class) = @_; - return $_ua if ($_ua); - $_ua = Lemonldap::NG::Common::UserAgent->new( { - lwpOpts => $class->tsv->{lwpOpts}, - lwpSslOpts => $class->tsv->{lwpSslOpts} - } - ); - return $_ua; -} - 1; diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm index 48afedd26..41f75d51e 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/DevOps.pm @@ -8,9 +8,14 @@ our $VERSION = '2.0.15'; our $_ua; sub ua { - return $_ua - ? $_ua - : Lemonldap::NG::Common::UserAgent->new( $_[0]->localConfig ); + my ($class) = @_; + return $_ua if $_ua; + $_ua = Lemonldap::NG::Common::UserAgent->new( { + lwpOpts => $class->tsv->{lwpOpts}, + lwpSslOpts => $class->tsv->{lwpSslOpts} + } + ); + return $_ua; } sub checkMaintenanceMode { From 04da19f0c8d49f128d41740b0379a35fec79af60 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Thu, 7 Apr 2022 22:59:20 +0200 Subject: [PATCH 04/35] Typos --- .../NG/Handler/ApacheMP2/FCGIClient.pm | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm index 6de7909c5..93e381759 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/FCGIClient.pm @@ -1,4 +1,4 @@ -# Apache2 FastCGI client to query remote LLNG FastCGI server +# Apache2 FastCGI client to query remote LL::NG FastCGI server # package Lemonldap::NG::Handler::ApacheMP2::FCGIClient; @@ -21,7 +21,7 @@ use constant REDIRECT => Apache2::Const::REDIRECT; use constant DECLINED => Apache2::Const::DECLINED; use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR; -our $VERSION = '2.0.14'; +our $VERSION = '2.0.15'; sub handler { my ( $class, $r ) = @_; @@ -43,11 +43,13 @@ sub handler { SERVER_PORT => $r->get_server_port, REQUEST_METHOD => $r->method, }; + foreach (qw(VHOSTTYPE RULES_URL HTTPS_REDIRECT PORT_REDIRECT)) { if ( my $t = $r->dir_config($_) ) { $env->{$_} = $t; } } + $r->headers_in->do( sub { my $h = shift; @@ -89,17 +91,14 @@ sub handler { return REDIRECT; } - if ( $hdrs{'Lm-Remote-User'} ) { - $r->user( $hdrs{'Lm-Remote-User'} ); - } - if ( $hdrs{'Lm-Remote-Custom'} ) { - $r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} ); - } + $r->user( $hdrs{'Lm-Remote-User'} ) if $hdrs{'Lm-Remote-User'}; + $r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} ) + if $hdrs{'Lm-Remote-Custom'}; my $i = 1; while ( $hdrs{"Headername$i"} ) { $r->headers_in->set( $hdrs{"Headername$i"} => $hdrs{"Headervalue$i"} ) - if ( $hdrs{"Headervalue$i"} ); + if $hdrs{"Headervalue$i"}; $i++; } $status = DECLINED if ( $status < 300 ); @@ -129,6 +128,9 @@ In apache2.conf: PerlSetVar VHOSTTYPE DevOps # or PerlSetVar VHOSTTYPE DevOpsST PerlSetVar RULES_URL http://app.tld/rules.json + PerlSetVar HOST HTTP_HOST + PerlSetVar PORT_REDIRECT SERVER_PORT + PerlSetVar HTTPS_REDIRECT HTTPS ... @@ -148,7 +150,7 @@ L =over -=item LemonLDAP::NG team L +=item LemonLDAP::NG team L =back @@ -160,7 +162,7 @@ L =head1 DOWNLOAD Lemonldap::NG is available at -L +L =head1 COPYRIGHT AND LICENSE From 5783a2d2995c8dcf83f7112df58bff2844e20a21 Mon Sep 17 00:00:00 2001 From: Yadd Date: Fri, 8 Apr 2022 12:10:47 +0200 Subject: [PATCH 05/35] Little makefile error --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 424600860..f7fd63edc 100644 --- a/Makefile +++ b/Makefile @@ -1105,7 +1105,7 @@ debian-dist: clean @cp lemonldap-ng-$(VERSION)/_example/etc/api-apache2.X.conf lemonldap-ng-$(VERSION)/_example/etc/api-apache2.conf @cp lemonldap-ng-$(VERSION)/_example/etc/test-apache2.X.conf lemonldap-ng-$(VERSION)/_example/etc/test-apache2.conf @rm -rf lemonldap-ng-$(VERSION)/lemonldap-ng-$(VERSION) - @find lemonldap-ng-$(VERSION)/ -name node_modules -exec rm -rf '{}' \; + -@find lemonldap-ng-$(VERSION)/ -name node_modules -exec rm -rf '{}' \; @$(COMPRESS) lemonldap-ng_$(VERSION).orig.$(COMPRESSSUFFIX) lemonldap-ng-$(VERSION) @rm -rf lemonldap-ng-$(VERSION) From ac105851ff54c680b21cb286b30c83b88aee2572 Mon Sep 17 00:00:00 2001 From: Yadd Date: Fri, 8 Apr 2022 12:16:54 +0200 Subject: [PATCH 06/35] make manifest --- lemonldap-ng-portal/MANIFEST | 1 - 1 file changed, 1 deletion(-) diff --git a/lemonldap-ng-portal/MANIFEST b/lemonldap-ng-portal/MANIFEST index 02f1f65dc..914a4892e 100644 --- a/lemonldap-ng-portal/MANIFEST +++ b/lemonldap-ng-portal/MANIFEST @@ -555,7 +555,6 @@ t/30-Auth-and-issuer-SAML-Artifact-with-SOAP-SLO-IdP-initiated.t t/30-Auth-and-issuer-SAML-Artifact-with-SOAP-SLO.t t/30-Auth-and-issuer-SAML-Metadata.t t/30-Auth-and-issuer-SAML-NameID.t -t/30-Auth-and-issuer-SAML-POST-Hook.t t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t t/30-Auth-and-issuer-SAML-POST-Missing-SLO.t t/30-Auth-and-issuer-SAML-POST.t From 697f44d200d6a33e53cced44c396722cf79fa676 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 12 Apr 2022 14:13:48 +0000 Subject: [PATCH 07/35] improve doc package --- Makefile | 18 ++---------------- doc/sources/admin/conf.py | 2 ++ 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index f7fd63edc..2f81be628 100644 --- a/Makefile +++ b/Makefile @@ -887,23 +887,9 @@ install_examples_site: install_doc_site: # Offline documentation install @rm -rf $(RDEFDOCDIR) - # Install doc directories @install -v -d -m 755 $(RDEFDOCDIR) - @cd doc && find * -type d |(cd $(RDEFDOCDIR); xargs install -v -d -m 755) && cd - - # Install HTML files - @cd doc && for f in `find * -type f -name '*.html'`; do \ - echo "Installing $$f"; \ - ../scripts/transform-templates \ - usedebianlibs $(USEDEBIANLIBS) \ - useexternallibs $(USEEXTERNALLIBS) \ - jsminified $(JSCOMPRESS) \ - cssminified $(CSSCOMPRESS) <$$f \ - > $(RDEFDOCDIR)/$$f; \ - done && cd - - # Install other files - @cd doc && for f in `find * -type f ! -name '*.html'`; do \ - install -v -m 644 $$f $(RDEFDOCDIR)/$$f; \ - done && cd - + @cd doc && find index.html pages/* -type f ! -path '*/.*' -exec install -v -m 644 -D '{}' $(RDEFDOCDIR)/'{}' \; && cd - + # Remove js @cd $(RDEFDOCDIR) && if test "$(USEEXTERNALLIBS)" = "yes"; then \ rm -rvf $(DOCEXTERNALLIBS); \ diff --git a/doc/sources/admin/conf.py b/doc/sources/admin/conf.py index d0c86b2a7..154ac0e1d 100644 --- a/doc/sources/admin/conf.py +++ b/doc/sources/admin/conf.py @@ -138,6 +138,8 @@ if 'LLNGSPHINXWEBSITE' in os.environ: import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' html_theme_options = {} +else: + html_copy_source = False # html_theme_options = {} From bc9698c6602cc0e3bd5e95e8213c3a86eb52d079 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Wed, 20 Apr 2022 09:52:54 +0200 Subject: [PATCH 08/35] Fix icons in register done email --- .../site/templates/common/mail_register_done.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl b/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl index 36b07bc5f..c7eafc5df 100644 --- a/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl +++ b/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl @@ -7,7 +7,7 @@

Your login is -go +go
Your password is From c73188edf6bcc77e0ce18441d4a88b9e98c8585e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Wed, 20 Apr 2022 16:42:27 +0200 Subject: [PATCH 09/35] Documentation to connect Sympa with CAS protocol --- doc/sources/admin/applications.rst | 2 +- doc/sources/admin/applications/sympa.rst | 59 +++++++++++++++++++++--- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/doc/sources/admin/applications.rst b/doc/sources/admin/applications.rst index a20652af1..cb549a684 100644 --- a/doc/sources/admin/applications.rst +++ b/doc/sources/admin/applications.rst @@ -136,7 +136,7 @@ Application Configuration .. image:: applications/simplesamlphp_logo.png :doc:`simpleSAMLphp` ✔ .. image:: applications/spring_logo.png :doc:`Spring` ✔ .. image:: applications/symfony_logo.png :doc:`Symfony` ✔ -.. image:: applications/sympa_logo.png :doc:`Sympa` ✔ +.. image:: applications/sympa_logo.png :doc:`Sympa` ✔ ✔ .. image:: applications/tomcat_logo.png :doc:`Tomcat` ✔ .. image:: applications/wekan-logo.png :doc:`Wekan` ✔ .. image:: applications/wiki.js.svg :doc:`Wiki.js` ✔ diff --git a/doc/sources/admin/applications/sympa.rst b/doc/sources/admin/applications/sympa.rst index 11951ce15..5e28cf754 100644 --- a/doc/sources/admin/applications/sympa.rst +++ b/doc/sources/admin/applications/sympa.rst @@ -8,9 +8,59 @@ Presentation `Sympa `__ is a mailing list manager. -To configure SSO with Sympa, use **Magic authentication**: a special SSO -URL is protected by LL::NG, Sympa will display a button for users who -wants to use this feature. +To configure SSO with Sympa, you have the choice between: + * CAS + * **Magic authentication**: a special SSO URL is protected by LL::NG, Sympa will display a button for users who wants to use this feature. + +We recommend to use CAS. + +CAS +--- + + +Sympa configuration +~~~~~~~~~~~~~~~~~~~ + +Edit the file "auth.conf", for example: + +:: + + vi /etc/sympa/auth.conf + +And fill it: + +:: + + cas + base_url https://auth.example.com/cas + non_blocking_redirection on + auth_service_name SSO + ldap_host ldap.example.com:389 + ldap_get_email_by_uid_filter (uid=[uid]) + ldap_timeout 7 + ldap_suffix dc=example,dc=com + ldap_scope sub + ldap_email_attribute mail + +Restart services: + +:: + + service sympa restart + service apache2 restart + +See also `official documentation `__ + +LemonLDAP::NG configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Declare CAS application in the configuration, register the service URL. + +No attributes are needed. + + +Magic authentication +-------------------- .. tip:: @@ -19,9 +69,6 @@ wants to use this feature. removed since it works only with Sympa-5 which has been deprecated -Configuration -------------- - Sympa configuration ~~~~~~~~~~~~~~~~~~~ From 9314c2f356e0ee23038593bc955df2ebb65efd6b Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 23 Apr 2022 17:09:18 +0200 Subject: [PATCH 10/35] Improve ServiceToken doc --- doc/sources/admin/servertoserver.rst | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/sources/admin/servertoserver.rst b/doc/sources/admin/servertoserver.rst index 8e326e5db..382b88389 100644 --- a/doc/sources/admin/servertoserver.rst +++ b/doc/sources/admin/servertoserver.rst @@ -5,16 +5,16 @@ In modern applications, web application may need to request some other web applications on behalf of the authenticated users. There are three ways to do this: -- the Ugly : provide to all applications SSO cookie. Not secured +- the Ugly: provide to all applications SSO cookie. Not secured because SSO cookie can be caught and used everywhere, every time by everyone!!! **NOT RECOMMENDED**. -- the Bad (:doc:`Secure Token Handler`) - : **Deprecated**. Can be used in specific cases -- the Good (Service Token Handler): See below ! (Thanks Sergio...) +- the Bad (:doc:`Secure Token Handler`): **Deprecated**. + Should be used for specific cases +- the Good (Service Token Handler): See below! (Thanks Sergio...) The "Bad" method consists to give the token (cookie value) to WebApp1 which uses it as cookie header in its request. Since 2.0 version, LL::NG -gives a better way (the Good !) to do this by using limited scope +gives a better way (the Good!) to do this by using limited scope tokens. Tokens are time limited (30 seconds by default) and URL restricted. @@ -24,22 +24,22 @@ Tokens are time limited (30 seconds by default) and URL restricted. Webapp1 handler configuration ----------------------------- -Select **Main** handler type to protect WebApp1 and insert a header -named **X-Llng-Token** filled with this value: +Select **Main** handler type to protect WebApp1 and append a header containing: .. code-block:: perl token( $_session_id, 'webapp2.example.com', 'webapp3.example.com', 'serviceHeader1=webapp1.example.com', "testHeader=$uid" ) WebApp1 can read this header and use it in its requests by setting the -``X-Llng-Token`` header. The token is built by using the session ID and -authorized virtualhosts list. By default, the Service Token is only -available during 30 seconds and for specified virtualhosts. The token -can be use to send service headers to webapp2 like origin host by -example. +``X-LLNG-TOKEN`` header. The token is built by using the ``token`` extended +with session ID and authorized virtualhosts list parameters. A Service Token is valide +for the specified virtual hosts only and during 30 seconds by default. It can also be +used for sending service headers (headerName1=headerValue1) to requested +apps. Can be useful to send the origin host by example. Service headers are +sent to ALL requested applications. -You can set ServiceToken TTL in the virtualHost options in Manager for -each required virtualHost. +You can set Service Token TTL by editing virtualHost options in Manager +for each requested virtualHost. You can also set ServiceToken default timeout (30 seconds) by editing ``lemonldap-ng.ini`` in section [handler]: @@ -58,7 +58,7 @@ Webapp2 handler configuration ----------------------------- Change handler type to **ServiceToken**. So it is able to manage both -user and server connections. And that's all ! +user and server connections. And that's all! .. |Kinematic| image:: documentation/server_to_server.png From 826308fbbfb946f34ae4c011ac121ec215b682c3 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 26 Apr 2022 19:08:46 +0200 Subject: [PATCH 11/35] Fix check after saveConf (#2742) --- lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm | 2 +- lemonldap-ng-common/scripts/convertConfig | 2 +- lemonldap-ng-common/scripts/importMetadata | 2 +- lemonldap-ng-common/scripts/rotateOidcKeys | 2 +- .../lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm index 9cdbe8fd9..c286e7796 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm @@ -115,7 +115,7 @@ sub new { # Serialize $conf and call store(). # @param $conf Lemonldap::NG configuration hashRef # @param %args Parameters -# @return Number of the saved configuration, 0 in case of error. +# @return Number of the saved configuration, <=0 in case of error. sub saveConf { my ( $self, $conf, %args ) = @_; diff --git a/lemonldap-ng-common/scripts/convertConfig b/lemonldap-ng-common/scripts/convertConfig index 2ca87d784..c80069c8a 100755 --- a/lemonldap-ng-common/scripts/convertConfig +++ b/lemonldap-ng-common/scripts/convertConfig @@ -112,7 +112,7 @@ foreach (@available) { next if ( $opts{force} ); exit 6; } - if ( my $r = $new->saveConf( $conf, %newargs ) ) { + if ( $new->saveConf( $conf, %newargs ) > 0 ) { print "Conf $conf->{cfgNum} stored\n"; next; } diff --git a/lemonldap-ng-common/scripts/importMetadata b/lemonldap-ng-common/scripts/importMetadata index 13b534428..e2abf93f5 100755 --- a/lemonldap-ng-common/scripts/importMetadata +++ b/lemonldap-ng-common/scripts/importMetadata @@ -466,7 +466,7 @@ if ( !$opts{'dry-run'} ) { print "[OK] Configuration $numConf saved\n"; $exitCode = 0; } - unless ($numConf) { + unless ( $numConf > 0 ) { print "[ERROR] Unable to save configuration\n"; $exitCode = 1; } diff --git a/lemonldap-ng-common/scripts/rotateOidcKeys b/lemonldap-ng-common/scripts/rotateOidcKeys index 3a545cf92..c8b65b7b6 100755 --- a/lemonldap-ng-common/scripts/rotateOidcKeys +++ b/lemonldap-ng-common/scripts/rotateOidcKeys @@ -50,7 +50,7 @@ $conf->{oidcServicePrivateKeySig} = $keys->{private}; $conf->{oidcServicePublicKeySig} = $keys->{public}; $conf->{oidcServiceKeyIdSig} = $keys->{id}; -$lmconf->saveConf($conf) or die $Lemonldap::NG::Common::Conf::msg; +( $lmconf->saveConf($conf) > 0 ) or die $Lemonldap::NG::Common::Conf::msg; print "Configuration saved\n" if $debug; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm index f0c24567a..918eb24b6 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/OpenIDConnect.pm @@ -1962,7 +1962,7 @@ sub registration { $self->conf->{oidcServiceDynamicRegistrationExtraClaims}; } - if ( $self->confAcc->saveConf($conf) ) { + if ( $self->confAcc->saveConf($conf) > 0 ) { # Reload RP list $self->loadRPs(); From 411c78c880424b2bacf72fd28d3f13c6794c6d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Wed, 27 Apr 2022 09:45:13 +0200 Subject: [PATCH 12/35] Fix values override in auth combination doc --- doc/sources/admin/authcombination.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/sources/admin/authcombination.rst b/doc/sources/admin/authcombination.rst index 85b4eff0f..3528c9b3b 100644 --- a/doc/sources/admin/authcombination.rst +++ b/doc/sources/admin/authcombination.rst @@ -39,7 +39,7 @@ must set: - overloaded parameters: you can redefine any LLNG string parameters. For example, if you use 2 different LDAP, the first can use normal configuration and for the second, overwritten parameter can redefine - ldapServer,... + ldapServer or any existing parameter. .. note:: @@ -63,12 +63,13 @@ parameters. For example, if DBI is configured to use PostgreSQL but DB2 is a MySQL DB, you can override the "dbiChain" parameter. -You can also override a complex key like ldapExportedVars, by setting a -JSON value: +The over parameter is a HASH ref where keys are attributes names and values are the overriden value. +To override a complex key like ldapExportedVars, you must use a JSON value, as the over parameter +expect string values: .. code-block:: javascript - {"cn" => "cn", "uid" => "sAMAccounName", "mail" => "mail"} + {"cn": "cn", "uid": "sAMAccounName", "mail": "mail"} .. attention:: From 1d597f64e52a74cf2c770277f0294b36d4b78e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Wed, 27 Apr 2022 12:31:50 +0200 Subject: [PATCH 13/35] Documentation for auth/user/password REST services --- doc/sources/admin/index_plugins.rst | 1 + doc/sources/admin/restauthuserpwdbackend.rst | 90 ++++++++++++++++++++ doc/sources/admin/restservices.rst | 3 + 3 files changed, 94 insertions(+) create mode 100644 doc/sources/admin/restauthuserpwdbackend.rst diff --git a/doc/sources/admin/index_plugins.rst b/doc/sources/admin/index_plugins.rst index 5dbbcda8c..f8e628b08 100644 --- a/doc/sources/admin/index_plugins.rst +++ b/doc/sources/admin/index_plugins.rst @@ -28,5 +28,6 @@ Plugins resetpassword resetcertificate restservices + restauthuserpwdbackend soapservices stayconnected diff --git a/doc/sources/admin/restauthuserpwdbackend.rst b/doc/sources/admin/restauthuserpwdbackend.rst new file mode 100644 index 000000000..c4e2e5140 --- /dev/null +++ b/doc/sources/admin/restauthuserpwdbackend.rst @@ -0,0 +1,90 @@ +REST auth/user/password backend +=============================== + +LL::NG Portal provides REST end points for auth/user/password: + +- POST /proxy/pwdConfirm: check password +- POST /proxy/getUser: get user data +- POST /proxy/pwdReset: update password + +These end points can be used to connect another LemonLDAP::NG server using :doc:`REST authentication backend`. + +API +--- + +Password confirm +~~~~~~~~~~~~~~~~ + +POST a JSON structure with ``user`` and ``password``. +It will return a JSON structure with ``result`` parameter (``true`` or ``false``). + +Request: + +.. code:: + + curl -H "Accept: application/json" -d '{"user":"dwho","password":"dwho"}' https://auth.example.com/proxy/pwdConfirm + +Response: + +.. code-block:: javascript + + {"result":true} + +Get user data +~~~~~~~~~~~~~ + +POST a JSON structure with ``user``. +It will return a JSON structure with ``result`` and ``info`` parameters. + +Request: + +.. code:: + + curl -H "Accept: application/json" -d '{"user":"rtyler"}' https://auth.example.com/proxy/getUser + +Response: + +.. code-block:: javascript + + {"info":{"_utime":1651055131,"hGroups":{"users":{"name":"users"},"earthlings":{"name":"earthlings"}},"ipAddr":"127.0.0.1","_auth":"Demo","_url":null,"uid":"rtyler","mail":"rtyler@badwolf.org","_userDB":"Demo","_startTime":"20220427122531","UA":"curl/7.68.0","cn":"Rose Tyler","_user":"rtyler","_language":"en","groups":"users; earthlings","_whatToTrace":"rtyler"},"result":true} + +Update password +~~~~~~~~~~~~~~~ + +POST a JSON structure with ``user`` or ``mail`` and ``password``. +It will return a JSON structure with ``result`` parameter. + +Request: + +.. code:: + + curl -H "Accept: application/json" -d '{"user":"rtyler","password":"secret"}' https://auth.example.com/proxy/pwdReset + +Response: + +.. code-block:: javascript + + {"result":true} + +Setup +----- + +Manager +~~~~~~~ + +First, activate REST in ``General parameters`` » ``Plugins`` » +``Portal servers`` » ``REST authentication server`` and ``REST password reset server``. + +Apache +~~~~~~ + +REST end points access must be allowed in Apache portal +configuration (for example, access by IP range): + +.. code-block:: apache + + # REST/SOAP functions for proxy auth and password reset (disabled by default) + + Require ip 192.168.2.0/24 + + diff --git a/doc/sources/admin/restservices.rst b/doc/sources/admin/restservices.rst index 56e6859e3..5e2065955 100644 --- a/doc/sources/admin/restservices.rst +++ b/doc/sources/admin/restservices.rst @@ -21,6 +21,9 @@ example: $env->{HTTP_ACCEPT} !~ m:application/json: + +Another solution is using the :doc:`REST auth/user/password backend`. + API ^^^ From 2669b4143d4a62aaa9bbba1bae189483af3ba063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20OUDOT?= Date: Fri, 29 Apr 2022 11:50:18 +0200 Subject: [PATCH 14/35] Fix CLI example for CAS application doc --- doc/sources/admin/cli_examples.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/sources/admin/cli_examples.rst b/doc/sources/admin/cli_examples.rst index e936080af..4762fa7a3 100644 --- a/doc/sources/admin/cli_examples.rst +++ b/doc/sources/admin/cli_examples.rst @@ -301,7 +301,7 @@ In this example we have: /usr/share/lemonldap-ng/bin/lemonldap-ng-cli -yes 1 \ addKey \ casAppMetaDataExportedVars/testapp mail mail \ - casAppMetaDataExportedVars/testapp cn cn + casAppMetaDataExportedVars/testapp cn cn \ casAppMetaDataOptions/testapp casAppMetaDataOptionsService 'https://testapp.example.com/' Configure SAML Identity Provider From 96f6667f24c35e58ec99189510bee2381a92d454 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 30 Apr 2022 09:52:37 +0200 Subject: [PATCH 15/35] Propagate to MFA #1877 --- .../lib/Lemonldap/NG/Portal/Main/SecondFactor.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm index 35bf28eeb..657dfc511 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm @@ -134,9 +134,9 @@ sub _verify { "Update sessionInfo with new authenticationLevel: $l"); $req->sessionInfo->{authenticationLevel} = $l; - # Compute macros & local groups again with new authenticationLevel - $self->logger->debug("Compute macros and local groups..."); - $req->steps( [ 'setMacros', 'setLocalGroups' ] ); + # Compute macros & groups with new authenticationLevel + $self->logger->debug("Compute macros and groups..."); + $req->steps( [ $self->p->groupsAndMacros, 'setLocalGroups' ] ); if ( my $error = $self->p->process($req) ) { $self->logger->debug("SFA: Process returned error: $error"); $req->error($error); From ab8cc97a5287281967eab2bde097964b73ebd3f4 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sat, 30 Apr 2022 09:52:50 +0200 Subject: [PATCH 16/35] Fix warning --- lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm index 13eb81678..122c1e42a 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm @@ -156,7 +156,7 @@ sub setGroups { my $groups = $req->sessionInfo->{groups} || ''; my $hGroups = $req->sessionInfo->{hGroups} || {}; for my $grp ( keys %demoGroups ) { - if ( grep { $_ eq $user } @{ $demoGroups{$grp} } ) { + if ( grep { $user && $user eq $_ } @{ $demoGroups{$grp} } ) { $hGroups->{$grp} = { 'name' => $grp }; $groups = ($groups) From 64d8dcb793efee96384c143b67b92402a1ec68b7 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Sat, 19 Mar 2022 11:22:02 +0100 Subject: [PATCH 17/35] Add log when 2FA is attempted (#2732) --- .../lib/Lemonldap/NG/Portal/2F/Engines/Default.pm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm index 43b1a7c53..034f2aa7c 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/2F/Engines/Default.pm @@ -367,6 +367,10 @@ sub run { # If only one 2F is authorized, display it unless ($#am) { + $self->userLogger->info( 'Second factor ' + . $am[0]->prefix + . '2F selected for ' + . $req->sessionInfo->{ $self->conf->{whatToTrace} } ); my $res = $am[0]->run( $req, $token ); $req->authResult($res); return $res; @@ -437,6 +441,10 @@ sub _choice { my $ch = $req->param('sf'); foreach my $m ( @{ $self->sfModules } ) { if ( $m->{m}->prefix eq $ch ) { + $self->userLogger->info( 'Second factor ' + . $m->{m}->prefix + . '2F selected for ' + . $req->sessionInfo->{ $self->conf->{whatToTrace} } ); my $res = $m->{m}->run( $req, $token ); $req->authResult($res); return $self->p->do( From ef295ddd55d85f76a676f0ca4325a16be2e7acd2 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Fri, 11 Mar 2022 17:47:36 +0100 Subject: [PATCH 18/35] Add _2f session key after 2FA success (#2726) --- .../lib/Lemonldap/NG/Portal/Main/SecondFactor.pm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm index 657dfc511..8422a329f 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/SecondFactor.pm @@ -165,9 +165,16 @@ sub _verify { authenticationLevel => $l, groups => $req->sessionInfo->{groups}, hGroups => $req->sessionInfo->{hGroups}, + _2f => $self->prefix, %macros } ); + } else { + # Only update _2f session key + $self->p->updateSession($req, + { + _2f => $self->prefix, + }); } $req->authResult(PE_SENDRESPONSE); From 9da6310037b6eb98b063842c973028e2092423c7 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Fri, 11 Mar 2022 17:49:28 +0100 Subject: [PATCH 19/35] Add method in test lib to check session attributes --- lemonldap-ng-portal/t/test-lib.pm | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lemonldap-ng-portal/t/test-lib.pm b/lemonldap-ng-portal/t/test-lib.pm index 2f794eb6c..c524df8c4 100644 --- a/lemonldap-ng-portal/t/test-lib.pm +++ b/lemonldap-ng-portal/t/test-lib.pm @@ -56,6 +56,7 @@ C call I<(see below)>. use strict; use Data::Dumper; use File::Find; +use JSON; use LWP::UserAgent; use Time::Fake; use URI::Escape; @@ -376,6 +377,31 @@ sub expectAuthenticatedAs { count(1); } +=head4 expectSessionAttributes($app,$id,%attributes) + +Verify that the session contains attributes with these values + +=cut + +sub expectSessionAttributes { + my ( $app, $id, %attributes ) = @_; + my $res; + ok( + $res = $app->_get("/sessions/global/$id"), + "Get session using restSessionServer" + ); + count(1); + expectOK($res); + ok( $res = eval { from_json( $res->[2]->[0] ) }, + "Deserialize session content" ); + count(1); + for my $attr ( keys %attributes ) { + is( $res->{$attr}, $attributes{$attr}, + "Session has correct value for $attr" ); + count(1); + } +} + =head4 expectOK($res) Verify that returned code is 200 From 4a0ba0fea95ee8bf103a421cca4e3ff280c28fc2 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Fri, 11 Mar 2022 17:56:24 +0100 Subject: [PATCH 20/35] Unit tests for #2726 --- lemonldap-ng-portal/t/75-2F-Registers.t | 3 +++ lemonldap-ng-portal/t/77-2F-Extra.t | 2 ++ 2 files changed, 5 insertions(+) diff --git a/lemonldap-ng-portal/t/75-2F-Registers.t b/lemonldap-ng-portal/t/75-2F-Registers.t index 491705c3a..210ed89af 100644 --- a/lemonldap-ng-portal/t/75-2F-Registers.t +++ b/lemonldap-ng-portal/t/75-2F-Registers.t @@ -29,6 +29,7 @@ SKIP: { u2fSelfRegistration => 1, u2fActivation => 1, u2fAuthnLevel => 5, + restSessionServer =>1, skipUpgradeConfirmation => 1, sfManagerRule => '$uid eq "dwho"', portalMainLogo => 'common/logos/logo_llng_old.png', @@ -151,6 +152,7 @@ SKIP: { 'Post code' ); $id = expectCookie($res); + expectSessionAttributes($client, $id, _2f => "totp"); # Get 2F register form ok( @@ -440,6 +442,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ== 'Push U2F signature' ); $id = expectCookie($res); + expectSessionAttributes($client, $id, _2f => "u"); ok( $res = $client->_get( '/2fregisters', diff --git a/lemonldap-ng-portal/t/77-2F-Extra.t b/lemonldap-ng-portal/t/77-2F-Extra.t index dafa7bfc5..f2e69c25d 100644 --- a/lemonldap-ng-portal/t/77-2F-Extra.t +++ b/lemonldap-ng-portal/t/77-2F-Extra.t @@ -84,6 +84,7 @@ ok( ); count(1); my $id = expectCookie($res); + expectSessionAttributes($client, $id, _2f => "work"); $client->logout($id); clean_sessions(); @@ -167,6 +168,7 @@ ok( ); count(1); $id = expectCookie($res); +expectSessionAttributes($client, $id, _2f => "home"); # Verify Authn Level ok( $res = $client->_get("/sessions/global/$id"), 'Get session' ); From b4276b7c6a403dd18dee73404d18b499de375d2f Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Mon, 2 May 2022 17:35:48 +0200 Subject: [PATCH 21/35] Doc for #2726 --- doc/sources/admin/variables.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/sources/admin/variables.rst b/doc/sources/admin/variables.rst index 4ae851360..7609bb75c 100644 --- a/doc/sources/admin/variables.rst +++ b/doc/sources/admin/variables.rst @@ -46,6 +46,7 @@ Key Description \_auth Authentication module \_userDB User module \_passwordDB Password module +\_2f Second factor (if 2FA was used) \_issuerDB Issuer module (can be multivalued) \_authChoice User choice done if :doc:`authentication choice` was used \_authMulti Full name of authentication module (with ``#label``) used in Multi From 727afeefd2a822f918d6abbc4d37a5e8f8a43cd5 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Mon, 2 May 2022 17:35:59 +0200 Subject: [PATCH 22/35] Update session display in manager for #2726 --- lemonldap-ng-manager/site/coffee/sessions.coffee | 2 +- lemonldap-ng-manager/site/htdocs/static/js/sessions.js | 2 +- lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js | 2 +- lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js.map | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lemonldap-ng-manager/site/coffee/sessions.coffee b/lemonldap-ng-manager/site/coffee/sessions.coffee index 30fb474ff..9d4e7cb87 100644 --- a/lemonldap-ng-manager/site/coffee/sessions.coffee +++ b/lemonldap-ng-manager/site/coffee/sessions.coffee @@ -110,7 +110,7 @@ categories = dateTitle: ['_utime', '_startTime', '_updateTime', '_lastAuthnUTime', '_lastSeen'] connectionTitle: ['ipAddr', '_timezone', '_url'] authenticationTitle:['_session_id', '_user', '_password', 'authenticationLevel'] - modulesTitle: ['_auth', '_userDB', '_passwordDB', '_issuerDB', '_authChoice', '_authMulti', '_userDBMulti'] + modulesTitle: ['_auth', '_userDB', '_passwordDB', '_issuerDB', '_authChoice', '_authMulti', '_userDBMulti', '_2f'] saml: ['_idp', '_idpConfKey', '_samlToken', '_lassoSessionDump', '_lassoIdentityDump'] groups: ['groups', 'hGroups'] ldap: ['dn'] diff --git a/lemonldap-ng-manager/site/htdocs/static/js/sessions.js b/lemonldap-ng-manager/site/htdocs/static/js/sessions.js index 8b24ec4b7..0ec970524 100644 --- a/lemonldap-ng-manager/site/htdocs/static/js/sessions.js +++ b/lemonldap-ng-manager/site/htdocs/static/js/sessions.js @@ -122,7 +122,7 @@ dateTitle: ['_utime', '_startTime', '_updateTime', '_lastAuthnUTime', '_lastSeen'], connectionTitle: ['ipAddr', '_timezone', '_url'], authenticationTitle: ['_session_id', '_user', '_password', 'authenticationLevel'], - modulesTitle: ['_auth', '_userDB', '_passwordDB', '_issuerDB', '_authChoice', '_authMulti', '_userDBMulti'], + modulesTitle: ['_auth', '_userDB', '_passwordDB', '_issuerDB', '_authChoice', '_authMulti', '_userDBMulti', '_2f'], saml: ['_idp', '_idpConfKey', '_samlToken', '_lassoSessionDump', '_lassoIdentityDump'], groups: ['groups', 'hGroups'], ldap: ['dn'], diff --git a/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js b/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js index a4cf8db0a..22e5813c0 100644 --- a/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js +++ b/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js @@ -1 +1 @@ -!function(){var f={_whatToTrace:[function(e,t){return"groupBy=substr("+e+",1)"},function(e,t){return e+"="+t+"*&groupBy="+e},function(e,t){return e+"="+t}],ipAddr:[function(e,t){return"groupBy=net("+e+",16,1)"},function(e,t){return t.match(/:/)||(t+="."),e+"="+t+"*&groupBy=net("+e+",32,2)"},function(e,t){return t.match(/:/)||(t+="."),e+"="+t+"*&groupBy=net("+e+",48,3)"},function(e,t){return t.match(/:/)||(t+="."),e+"="+t+"*&groupBy=net("+e+",128,4)"},function(e,t){return e+"="+t+"&groupBy=_whatToTrace"},function(e,t,n){return n.replace(/\&groupBy.*$/,"")+"&_whatToTrace="+t}],_startTime:[function(e,t){return"groupBy=substr("+e+",8)"},function(e,t){return e+"="+t+"*&groupBy=substr("+e+",10)"},function(e,t){return e+"="+t+"*&groupBy=substr("+e+",11)"},function(e,t){return e+"="+t+"*&groupBy=substr("+e+",12)"},function(e,t){return e+"="+t+"*&groupBy=_whatToTrace"},function(e,t,n){return console.log(e),console.log(t),console.log(n),n.replace(/\&groupBy.*$/,"")+"&_whatToTrace="+t}],doubleIp:[function(e,t){return e},function(e,t){return"_whatToTrace="+t+"&groupBy=ipAddr"},function(e,t,n){return n.replace(/\&groupBy.*$/,"")+"&ipAddr="+t}],_session_uid:[function(e,t){return"groupBy=substr("+e+",1)"},function(e,t){return e+"="+t+"*&groupBy="+e},function(e,t){return e+"="+t}]},g={_whatToTrace:function(e,t,n,o){return console.log("overScheme => level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null},ipAddr:function(e,t,n,o){return console.log("overScheme => level",n,"over",o),0 level",n,"over",o),3 level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null}},M={dateTitle:["_utime","_startTime","_updateTime","_lastAuthnUTime","_lastSeen"],connectionTitle:["ipAddr","_timezone","_url"],authenticationTitle:["_session_id","_user","_password","authenticationLevel"],modulesTitle:["_auth","_userDB","_passwordDB","_issuerDB","_authChoice","_authMulti","_userDBMulti"],saml:["_idp","_idpConfKey","_samlToken","_lassoSessionDump","_lassoIdentityDump"],groups:["groups","hGroups"],ldap:["dn"],OpenIDConnect:["_oidc_id_token","_oidc_OP","_oidc_access_token"],sfaTitle:["_2fDevices"],oidcConsents:["_oidcConsents"]},i={session:[{title:"deleteSession",icon:"trash"}],home:[]};angular.module("llngSessionsExplorer",["ui.tree","ui.bootstrap","llApp"]).controller("SessionsExplorerCtrl",["$scope","$translator","$location","$q","$http",function(H,t,r,e,o){var p,n,d;return H.links=links,H.menulinks=menulinks,H.staticPrefix=staticPrefix,H.scriptname=scriptname,H.formPrefix=formPrefix,H.impPrefix=impPrefix,H.sessionTTL=sessionTTL,H.availableLanguages=availableLanguages,H.waiting=!0,H.showM=!1,H.showT=!0,H.data=[],H.currentScope=null,H.currentSession=null,H.menu=i,H.translateP=t.translateP,H.translate=t.translate,H.translateTitle=function(e){return t.translateField(e,"title")},d="global",H.menuClick=function(e){if(e.popup)window.open(e.popup);else switch(e.action||(e.action=e.title),typeof e.action){case"function":e.action(H.currentNode,H);break;case"string":H[e.action]();break;default:console.log(typeof e.action)}return H.showM=!1},H.deleteOIDCConsent=function(e,t){var i=document.querySelectorAll(".data-"+t);return H.waiting=!0,o.delete(scriptname+"sessions/OIDCConsent/"+d+"/"+H.currentSession.id+"?rp="+e+"&epoch="+t).then(function(e){var t,n,o,r;for(H.waiting=!1,r=[],n=0,o=i.length;nt.title?1:e.title real attribute"),B.push(i)):P.push(i);return I=P.concat(B),L.push({title:"__attributesAndMacros__",nodes:I}),{_utime:E,nodes:L}};return H.currentScope=e,t=e.$modelValue.session,o.get(scriptname+"sessions/"+d+"/"+t).then(function(e){return H.currentSession=n(e.data),H.currentSession.id=t}),H.showT=!1},H.localeDate=function(e){return new Date(1e3*e).toLocaleString()},H.isValid=function(e,t){var n=r.path(),o=Date.now()/1e3;return console.log("Path",n),console.log("Session epoch",e),console.log("Current date",o),console.log("Session TTL",sessionTTL),e=o-e level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null},ipAddr:function(e,t,n,o){return console.log("overScheme => level",n,"over",o),0 level",n,"over",o),3 level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null}},M={dateTitle:["_utime","_startTime","_updateTime","_lastAuthnUTime","_lastSeen"],connectionTitle:["ipAddr","_timezone","_url"],authenticationTitle:["_session_id","_user","_password","authenticationLevel"],modulesTitle:["_auth","_userDB","_passwordDB","_issuerDB","_authChoice","_authMulti","_userDBMulti","_2f"],saml:["_idp","_idpConfKey","_samlToken","_lassoSessionDump","_lassoIdentityDump"],groups:["groups","hGroups"],ldap:["dn"],OpenIDConnect:["_oidc_id_token","_oidc_OP","_oidc_access_token"],sfaTitle:["_2fDevices"],oidcConsents:["_oidcConsents"]},i={session:[{title:"deleteSession",icon:"trash"}],home:[]};angular.module("llngSessionsExplorer",["ui.tree","ui.bootstrap","llApp"]).controller("SessionsExplorerCtrl",["$scope","$translator","$location","$q","$http",function(H,t,r,e,o){var p,n,d;return H.links=links,H.menulinks=menulinks,H.staticPrefix=staticPrefix,H.scriptname=scriptname,H.formPrefix=formPrefix,H.impPrefix=impPrefix,H.sessionTTL=sessionTTL,H.availableLanguages=availableLanguages,H.waiting=!0,H.showM=!1,H.showT=!0,H.data=[],H.currentScope=null,H.currentSession=null,H.menu=i,H.translateP=t.translateP,H.translate=t.translate,H.translateTitle=function(e){return t.translateField(e,"title")},d="global",H.menuClick=function(e){if(e.popup)window.open(e.popup);else switch(e.action||(e.action=e.title),typeof e.action){case"function":e.action(H.currentNode,H);break;case"string":H[e.action]();break;default:console.log(typeof e.action)}return H.showM=!1},H.deleteOIDCConsent=function(e,t){var i=document.querySelectorAll(".data-"+t);return H.waiting=!0,o.delete(scriptname+"sessions/OIDCConsent/"+d+"/"+H.currentSession.id+"?rp="+e+"&epoch="+t).then(function(e){var t,n,o,r;for(H.waiting=!1,r=[],n=0,o=i.length;nt.title?1:e.title real attribute"),B.push(i)):P.push(i);return I=P.concat(B),L.push({title:"__attributesAndMacros__",nodes:I}),{_utime:E,nodes:L}};return H.currentScope=e,t=e.$modelValue.session,o.get(scriptname+"sessions/"+d+"/"+t).then(function(e){return H.currentSession=n(e.data),H.currentSession.id=t}),H.showT=!1},H.localeDate=function(e){return new Date(1e3*e).toLocaleString()},H.isValid=function(e,t){var n=r.path(),o=Date.now()/1e3;return console.log("Path",n),console.log("Session epoch",e),console.log("Current date",o),console.log("Session TTL",sessionTTL),e=o-e Date: Mon, 9 May 2022 14:36:03 +0000 Subject: [PATCH 23/35] Fix version of selinux package dependency (#2749) --- rpm/lemonldap-ng.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpm/lemonldap-ng.spec b/rpm/lemonldap-ng.spec index 038ce697e..8b06237b1 100644 --- a/rpm/lemonldap-ng.spec +++ b/rpm/lemonldap-ng.spec @@ -205,7 +205,7 @@ Requires: lemonldap-ng-test = %{version}-%{release} # ! Not available in Centos7, you need to install lemonldap-ng-selinux manually # This ensures that the *-selinux package and all it’s dependencies are not pulled # into containers and other systems that do not use SELinux -Requires: (%{name}-selinux if selinux-policy-%{selinuxtype}) +Requires: (%{name}-selinux = %{version}-%{release} if selinux-policy-%{selinuxtype}) %endif From ba9cb5e1e50a76093f589e024e06e0741dfe6f42 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 00:15:38 +0200 Subject: [PATCH 24/35] Improve doc --- doc/sources/admin/exportedvars.rst | 13 ++++++++++--- doc/sources/admin/portalcustom.rst | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/sources/admin/exportedvars.rst b/doc/sources/admin/exportedvars.rst index 3f0354e7b..c5d8074a8 100644 --- a/doc/sources/admin/exportedvars.rst +++ b/doc/sources/admin/exportedvars.rst @@ -51,13 +51,20 @@ portal: - macros are used to extend (or rewrite) :doc:`exported variables`. A macro is stored as attributes: it can contain boolean results or any string -- macros can also be used to import environment variables *(these +- macros can also be used for importing environment variables *(these variables are in CGI format)*. Example: ``$ENV{HTTP_COOKIE}`` - groups are stored as a string with values separated by ''; '' - (default values separator) in the special attribute ``groups``: it - contains the names of groups whose rules were returned true for the + (default multivalues separator) in the special attribute ``groups``: it + contains names of groups whose rules were returned true for the current user. For example: +.. danger:: + + Macros can be used for rewriting or overloading exported variables + but it can lead to some side effects. Be aware of alphabetical order + and keep in mind that exported variables are set then macros and + groups are computed. + .. code-block:: perl $groups = group3; admin diff --git a/doc/sources/admin/portalcustom.rst b/doc/sources/admin/portalcustom.rst index 8c100d830..002e27612 100644 --- a/doc/sources/admin/portalcustom.rst +++ b/doc/sources/admin/portalcustom.rst @@ -361,7 +361,7 @@ Password Policy - **Minimal upper characters**: leave 0 to bypass the check - **Minimal digit characters**: leave 0 to bypass the check - **Minimal special characters**: leave 0 to bypass the check -- **Allowed special characters**: set '__ALL__' value to allow ALL special characters. A blanck value forbids ALL special characters (Note that ``_`` is not a special character) +- **Allowed special characters**: set '__ALL__' value to allow ALL special characters. A blank value forbids ALL special characters (Note that ``_`` is not a special character) .. _portalcustom-other-parameters: From c979adb9d21954f8bb8e0ffca30dbdf741e3c2e5 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 00:17:43 +0200 Subject: [PATCH 25/35] Display password policy only if enabled (#2733) --- .../lib/Lemonldap/NG/Portal/Main/Display.pm | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm index 91807576c..bd2aff221 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -10,11 +10,12 @@ use Mouse; use JSON; use URI; -has isPP => ( is => 'rw' ); -has speChars => ( is => 'rw' ); -has skinRules => ( is => 'rw' ); -has stayConnected => ( is => 'rw', default => sub { 0 } ); -has requireOldPwd => ( is => 'rw', default => sub { 1 } ); +has isPP => ( is => 'rw' ); +has speChars => ( is => 'rw' ); +has skinRules => ( is => 'rw' ); +has stayConnected => ( is => 'rw', default => sub { 0 } ); +has requireOldPwd => ( is => 'rw', default => sub { 1 } ); +has passwordPolicyActivation => ( is => 'rw', default => sub { 0 } ); sub displayInit { my ($self) = @_; @@ -48,6 +49,14 @@ sub displayInit { $self->logger->error("Bad stayConnected rule: $error"); } $self->stayConnected($rule); + $rule = + HANDLER->buildSub( + HANDLER->substitute( $self->conf->{passwordPolicyActivation} ) ); + unless ($rule) { + my $error = HANDLER->tsv->{jail}->error || 'Unable to compile rule'; + $self->logger->error("Bad passwordPolicyActivation rule: $error"); + } + $self->passwordPolicyActivation($rule); my $speChars = $self->conf->{passwordPolicySpecialChar} eq '__ALL__' @@ -259,12 +268,13 @@ sub display { DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword}, HIDE_OLDPASSWORD => 0, PPOLICY_NOPOLICY => !$self->isPP(), - DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy}, - PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, - PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, - PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, - PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, - PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, + DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy} + && $self->passwordPolicyActivation->( $req, $req->sessionInfo ), + PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, + PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, + PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, + PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, ( $self->requireOldPwd->( $req, $req->userData ) ? ( REQUIRE_OLDPASSWORD => 1 ) @@ -479,11 +489,13 @@ sub display { HIDE_OLDPASSWORD => $self->conf->{hideOldPassword}, DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword}, PPOLICY_NOPOLICY => !$self->isPP(), - DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy}, - PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, - PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, - PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, - PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy} + && $self->passwordPolicyActivation->( $req, + $req->sessionInfo ), + PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, + PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, + PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, + PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, ( $self->conf->{passwordPolicyMinSpeChar} || $self->speChars() From 362072578761351ef9ef17ab5e5bc158057695f7 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 00:18:19 +0200 Subject: [PATCH 26/35] Improve log --- .../lib/Lemonldap/NG/Portal/Password/Base.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Password/Base.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Password/Base.pm index ab4786887..2d9ad26bc 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Password/Base.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Password/Base.pm @@ -17,7 +17,7 @@ use Lemonldap::NG::Portal::Main::Constants qw( extends 'Lemonldap::NG::Portal::Main::Plugin'; -our $VERSION = '2.0.12'; +our $VERSION = '2.0.14'; # INITIALIZATION @@ -59,7 +59,8 @@ sub _modifyPassword { ) ); unless ($oldPwdRule) { - my $error = $self->p->HANDLER->tsv->{jail}->error || '???'; + my $error = + $self->p->HANDLER->tsv->{jail}->error || 'Unable to compile rule'; } my $pwdPolicyRule = $self->p->HANDLER->buildSub( @@ -68,7 +69,8 @@ sub _modifyPassword { ) ); unless ($pwdPolicyRule) { - my $error = $self->p->HANDLER->tsv->{jail}->error || '???'; + my $error = + $self->p->HANDLER->tsv->{jail}->error || 'Unable to compile rule'; } # Check if portal require old password From a79d78325761c0c5651d4f85f225e4f4aacebef4 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 00:21:53 +0200 Subject: [PATCH 27/35] Display password policy & use it to compile password regex (#2733) --- .../NG/Portal/Plugins/MailPasswordReset.pm | 81 ++++++++++++++----- 1 file changed, 62 insertions(+), 19 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm index ae507284f..eb40eb588 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm @@ -32,7 +32,7 @@ use Lemonldap::NG::Portal::Main::Constants qw( PE_PP_INSUFFICIENT_PASSWORD_QUALITY ); -our $VERSION = '2.0.12'; +our $VERSION = '2.0.14'; extends qw( Lemonldap::NG::Portal::Lib::SMTP @@ -58,6 +58,9 @@ has ott => ( # Captcha generator has captcha => ( is => 'rw' ); +# Password policy activation rule +has passwordPolicyActivationRule => ( is => 'rw', default => sub { 0 } ); + # INITIALIZATION sub init { @@ -70,6 +73,15 @@ sub init { if ( $self->conf->{captcha_mail_enabled} ) { $self->captcha( $self->p->loadModule('::Lib::Captcha') ) or return 0; } + + # Parse password policy activation rule + $self->passwordPolicyActivationRule( + $self->p->buildRule( + $self->conf->{passwordPolicyActivation}, + 'passwordPolicyActivation' + ) + ); + return 0 unless $self->passwordPolicyActivationRule; return 1; } @@ -442,8 +454,28 @@ sub changePwd { "Reset password request for $req->{sessionInfo}->{_user}"); # Generate a complex password - my $password = - $self->gen_password( $self->conf->{randomPasswordRegexp} ); + my $pwdRegEx; + if ( $self->passwordPolicyActivationRule->( $req, $req->sessionInfo ) + && !$self->conf->{randomPasswordRegexp} ) + { + my $uppers = $self->conf->{passwordPolicyMinUpper} || 3; + my $lowers = $self->conf->{passwordPolicyMinLower} || 5; + my $digits = $self->conf->{passwordPolicyMinDigit} || 2; + my $chars = + $self->conf->{passwordPolicyMinSize} - + $self->conf->{passwordPolicyMinUpper} - + $self->conf->{passwordPolicyMinLower} - + $self->conf->{passwordPolicyMinDigit}; + $chars = 1 if $chars < 1; + $pwdRegEx = "[A-Z]{$uppers}[a-z]{$lowers}\\d{$digits}.{$chars}"; + $self->logger->debug("Generated password RegEx: $pwdRegEx"); + } + else { + $pwdRegEx = + $self->conf->{randomPasswordRegexp} || '[A-Z]{3}[a-z]{5}.\d{2}'; + $self->logger->debug("Used password RegEx: $pwdRegEx"); + } + my $password = $self->gen_password($pwdRegEx); $self->logger->debug("Generated password: $password"); $req->data->{newpassword} = $password; $req->data->{confirmpassword} = $password; @@ -467,11 +499,13 @@ sub changePwd { } } - # Check password quality + # Check password quality if enabled require Lemonldap::NG::Portal::Password::Base; my $cpq = - $self->Lemonldap::NG::Portal::Password::Base::checkPasswordQuality( - $req->data->{newpassword} ); + $self->passwordPolicyActivationRule->( $req, $req->sessionInfo ) + ? $self->Lemonldap::NG::Portal::Password::Base::checkPasswordQuality( + $req->data->{newpassword} ) + : PE_OK; unless ( $cpq == PE_OK ) { $self->ott->setToken( $req, $req->sessionInfo ); return $cpq; @@ -555,9 +589,19 @@ sub setSecurity { sub display { my ( $self, $req ) = @_; - my $speChars = $self->conf->{passwordPolicySpecialChar}; + my $speChars = + $self->conf->{passwordPolicySpecialChar} eq '__ALL__' + ? '' + : $self->conf->{passwordPolicySpecialChar}; $speChars =~ s/\s+/ /g; $speChars =~ s/(?:^\s|\s$)//g; + my $isPP = + $self->conf->{passwordPolicyMinSize} + || $self->conf->{passwordPolicyMinLower} + || $self->conf->{passwordPolicyMinUpper} + || $self->conf->{passwordPolicyMinDigit} + || $self->conf->{passwordPolicyMinSpeChar} + || $speChars; $self->logger->debug( 'Display called with code: ' . $req->error ); my %tplPrm = ( @@ -576,7 +620,8 @@ sub display { STARTMAILTIME => $req->data->{startMailTime}, MAILALREADYSENT => $req->data->{mailAlreadySent}, MAIL => ( - $self->p->checkXSSAttack( 'mail', $req->{user} ) ? '' + $self->p->checkXSSAttack( 'mail', $req->{user} ) + ? '' : $req->{user} ), DISPLAY_FORM => 0, @@ -584,17 +629,15 @@ sub display { DISPLAY_CONFIRMMAILSENT => 0, DISPLAY_MAILSENT => 0, DISPLAY_PASSWORD_FORM => 0, - DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy}, - PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, - PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, - PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, - PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, - PPOLICY_ALLOWEDSPECHAR => $speChars, - ( - $speChars - ? ( PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar} ) - : () - ), + DISPLAY_PPOLICY => $isPP + && $self->conf->{portalDisplayPasswordPolicy} + && $self->passwordPolicyActivationRule->( $req, $req->sessionInfo ), + PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, + PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, + PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, + PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, + PPOLICY_ALLOWEDSPECHAR => $speChars, DISPLAY_GENERATE_PASSWORD => $self->conf->{portalDisplayGeneratePassword}, ); From 1bc427043ad1bd028f2514ac2dabcbf0fbfd7888 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 00:22:10 +0200 Subject: [PATCH 28/35] Update doc (#2733) --- doc/sources/admin/resetpassword.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/sources/admin/resetpassword.rst b/doc/sources/admin/resetpassword.rst index 448a38d3d..b4f0c36db 100644 --- a/doc/sources/admin/resetpassword.rst +++ b/doc/sources/admin/resetpassword.rst @@ -84,8 +84,6 @@ Then go in Manager, ``General Parameters`` » ``Plugins`` » - **Display generate password box**: display a checkbox to allow user to generate a new password instead of choosing one (default: disabled) - -:: - - * **Regexp for password generation**: Regular expression used to generate the password (default: [A-Z]{3}[a-z]{5}.\d{2}) + - **Regexp for password generation**: Regular expression used to generate the password. Set a blank value to use + password policy if enabled or default regexp will be employed: [A-Z]{3}[a-z]{5}.\d{2} From dcc6f2cbc9b8e7bcb1826fe43d4075349a26115f Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 22:08:28 +0200 Subject: [PATCH 29/35] Display policy if enabled (#2733) --- .../lib/Lemonldap/NG/Portal/Main/Display.pm | 27 +++++++++---------- .../NG/Portal/Plugins/MailPasswordReset.pm | 12 ++++----- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm index bd2aff221..0c76b0c75 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -268,13 +268,12 @@ sub display { DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword}, HIDE_OLDPASSWORD => 0, PPOLICY_NOPOLICY => !$self->isPP(), - DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy} - && $self->passwordPolicyActivation->( $req, $req->sessionInfo ), - PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, - PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, - PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, - PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, - PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, + DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy}, + PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, + PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, + PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, + PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, ( $self->requireOldPwd->( $req, $req->userData ) ? ( REQUIRE_OLDPASSWORD => 1 ) @@ -484,18 +483,16 @@ sub display { CHOICE_PARAM => $self->conf->{authChoiceParam}, CHOICE_VALUE => $req->data->{_authChoice}, OLDPASSWORD => $self->checkXSSAttack( 'oldpassword', - $req->data->{oldpassword} ) ? "" + $req->data->{oldpassword} ) ? '' : $req->data->{oldpassword}, HIDE_OLDPASSWORD => $self->conf->{hideOldPassword}, DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword}, PPOLICY_NOPOLICY => !$self->isPP(), - DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy} - && $self->passwordPolicyActivation->( $req, - $req->sessionInfo ), - PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, - PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, - PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, - PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy}, + PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, + PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, + PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, + PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, ( $self->conf->{passwordPolicyMinSpeChar} || $self->speChars() diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm index eb40eb588..13be761b8 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm @@ -629,13 +629,11 @@ sub display { DISPLAY_CONFIRMMAILSENT => 0, DISPLAY_MAILSENT => 0, DISPLAY_PASSWORD_FORM => 0, - DISPLAY_PPOLICY => $isPP - && $self->conf->{portalDisplayPasswordPolicy} - && $self->passwordPolicyActivationRule->( $req, $req->sessionInfo ), - PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, - PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, - PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, - PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy} && $isPP, + PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize}, + PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, + PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, + PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, PPOLICY_MINSPECHAR => $self->conf->{passwordPolicyMinSpeChar}, PPOLICY_ALLOWEDSPECHAR => $speChars, DISPLAY_GENERATE_PASSWORD => From 5490f60f7465ea846f61045c5cfb09928dd5d663 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 23:27:52 +0200 Subject: [PATCH 30/35] Improve unit tests (#2733) --- .../t/43-MailPasswordReset-DBI.t | 23 ++++++-- .../t/43-MailPasswordReset-with-captcha.t | 15 ++++- lemonldap-ng-portal/t/43-MailPasswordReset.t | 57 +++++++++++++++---- 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/lemonldap-ng-portal/t/43-MailPasswordReset-DBI.t b/lemonldap-ng-portal/t/43-MailPasswordReset-DBI.t index 3293c6806..760841348 100644 --- a/lemonldap-ng-portal/t/43-MailPasswordReset-DBI.t +++ b/lemonldap-ng-portal/t/43-MailPasswordReset-DBI.t @@ -13,7 +13,7 @@ BEGIN { } my ( $res, $user, $pwd ); -my $maintests = 17; +my $maintests = 19; my $mailSend = 0; my $mail2 = 0; @@ -54,7 +54,12 @@ SKIP: { dbiAuthPasswordHash => '', dbiDynamicHashEnabled => 0, dbiMailCol => 'mail', + portalDisplayPasswordPolicy => 1, + passwordPolicyActivation => 0, passwordResetAllowedRetries => 4, + passwordPolicyMinDigit => 2, + passwordPolicyMinSpeChar => 1, + passwordPolicySpecialChar => '__ALL__' } } ); @@ -141,8 +146,16 @@ SKIP: { # Post new password ( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' ); ok( $res->[2]->[0] =~ /newpassword/s, ' Ask for a new password #4' ); - - $query .= '&newpassword=zz&confirmpassword=zz'; + ok( + $res->[2]->[0] !~ /passwordPolicySpecialChar/, + ' Password special char list not found' + ); + ok( + $res->[2]->[0] =~ +/Minimal digit characters:<\/span> 2/, + ' Found password policy min digit == 2' + ); + $query .= '&newpassword=zz11#&confirmpassword=zz11#'; ok( $res = $client->_post( '/resetpwd', IO::String->new($query), @@ -157,8 +170,8 @@ SKIP: { ok( $res = $client->_post( '/', - IO::String->new('user=dwho&password=zz'), - length => 21 + IO::String->new('user=dwho&password=zz11#'), + length => 24 ), 'Auth query' ); diff --git a/lemonldap-ng-portal/t/43-MailPasswordReset-with-captcha.t b/lemonldap-ng-portal/t/43-MailPasswordReset-with-captcha.t index dbc765290..81e960e96 100644 --- a/lemonldap-ng-portal/t/43-MailPasswordReset-with-captcha.t +++ b/lemonldap-ng-portal/t/43-MailPasswordReset-with-captcha.t @@ -10,7 +10,7 @@ BEGIN { } my ( $res, $host, $url, $query ); -my $maintests = 16; +my $maintests = 18; my $mailSend = 0; my $mail2 = 0; @@ -33,6 +33,13 @@ SKIP: { requireToken => 1, portalDisplayResetPassword => 1, portalMainLogo => 'common/logos/logo_llng_old.png', + passwordPolicyActivation => 1, + passwordPolicyMinUpper => 1, + passwordPolicyMinLower => 1, + passwordPolicyMinDigit => 2, + passwordPolicyMinSpeChar => 1, + randomPasswordRegexp => '', + passwordPolicySpecialChar => '*#@' } } ); @@ -104,7 +111,7 @@ m#[2]->[0] =~ /newpassword/s, ' Ask for a new password' ); - $query .= '&newpassword=zz&confirmpassword=zz'; + $query .= '&reset=1'; # Post new password ok( @@ -115,7 +122,9 @@ m#Your new password is<\/span>/, 'New password sent' ); + ok( mail() =~ /(.+?)<\/b>/s, 'New generated password found' ); + ok( $1 =~ /[A-Z]{1}[a-z]{1}\d{2}[*#@]{1}/, 'New generated password matches' ); #print STDERR Dumper($query); } diff --git a/lemonldap-ng-portal/t/43-MailPasswordReset.t b/lemonldap-ng-portal/t/43-MailPasswordReset.t index bc456ca8a..7504c4226 100644 --- a/lemonldap-ng-portal/t/43-MailPasswordReset.t +++ b/lemonldap-ng-portal/t/43-MailPasswordReset.t @@ -10,7 +10,7 @@ BEGIN { } my ( $res, $user, $pwd ); -my $maintests = 12; +my $maintests = 18; SKIP: { eval @@ -21,15 +21,22 @@ SKIP: { my $client = LLNG::Manager::Test->new( { ini => { - logLevel => 'error', - useSafeJail => 1, - portalDisplayRegister => 1, - authentication => 'Demo', - userDB => 'Same', - passwordDB => 'Demo', - captcha_mail_enabled => 0, - portalDisplayResetPassword => 1, - portalMainLogo => 'common/logos/logo_llng_old.png', + logLevel => 'error', + useSafeJail => 1, + portalDisplayRegister => 1, + authentication => 'Demo', + userDB => 'Same', + passwordDB => 'Demo', + captcha_mail_enabled => 0, + portalDisplayResetPassword => 1, + portalMainLogo => 'common/logos/logo_llng_old.png', + portalDisplayPasswordPolicy => 1, + passwordPolicyActivation => 1, + passwordPolicyMinUpper => 1, + passwordPolicyMinLower => 1, + passwordPolicyMinDigit => 2, + passwordPolicyMinSpeChar => 1, + passwordPolicySpecialChar => '&%#' } } ); @@ -87,8 +94,34 @@ SKIP: { ); ( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' ); ok( $res->[2]->[0] =~ /newpassword/s, ' Ask for a new password' ); - - $query .= '&newpassword=zz&confirmpassword=zz'; + ok( $res->[2]->[0] =~ //, + ' Found password policy' ); + ok( + $res->[2]->[0] =~ +/Minimal lower characters:<\/span> 1/, + ' Found password policy min lower == 1' + ); + ok( + $res->[2]->[0] =~ +/Minimal upper characters:<\/span> 1/, + ' Found password policy min upper == 1' + ); + ok( + $res->[2]->[0] =~ +/Minimal digit characters:<\/span> 2/, + ' Found password policy min digit == 2' + ); + ok( + $res->[2]->[0] =~ +/Minimal special characters:<\/span> 1/, + ' Found password policy min speChar == 1' + ); + ok( + $res->[2]->[0] =~ +/Allowed special characters:<\/span> &%#/, + ' Found password special char list' + ); + $query .= '&newpassword=zZ11#&confirmpassword=zZ11#'; # Post new password ok( From 7424751919ec7da4d74f870020e799b852c950cb Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 23:28:09 +0200 Subject: [PATCH 31/35] Fix regex generator (#2733) --- .../lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm index 13be761b8..4b93481ec 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm @@ -467,7 +467,11 @@ sub changePwd { $self->conf->{passwordPolicyMinLower} - $self->conf->{passwordPolicyMinDigit}; $chars = 1 if $chars < 1; - $pwdRegEx = "[A-Z]{$uppers}[a-z]{$lowers}\\d{$digits}.{$chars}"; + $pwdRegEx = "[A-Z]{$uppers}[a-z]{$lowers}\\d{$digits}"; + $pwdRegEx .= + $self->conf->{passwordPolicySpecialChar} eq '__ALL__' + ? "\\W{$chars}" + : "[$self->{conf}->{passwordPolicySpecialChar}]{$chars}"; $self->logger->debug("Generated password RegEx: $pwdRegEx"); } else { From 46c0cdd1bb0652f2f1f230f9390c0a0bb94ff237 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 23:28:21 +0200 Subject: [PATCH 32/35] Update doc --- doc/sources/admin/contribute.rst | 2 +- doc/sources/admin/prereq.rst | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/sources/admin/contribute.rst b/doc/sources/admin/contribute.rst index d5feef67e..fc7135182 100644 --- a/doc/sources/admin/contribute.rst +++ b/doc/sources/admin/contribute.rst @@ -58,7 +58,7 @@ As *root:* apt install aptitude aptitude install vim make devscripts yui-compressor git git-gui libjs-uglify coffeescript cpanminus autopkgtest pkg-perl-autopkgtest - aptitude install libauth-yubikey-webclient-perl libnet-smtp-server-perl libtime-fake-perl libtest-output-perl libtest-pod-perl libtest-leaktrace-perl libtest-mockobject-perl uglifyjs + aptitude install libauth-yubikey-webclient-perl libnet-smtp-server-perl libtime-fake-perl libtest-output-perl libtest-pod-perl libtest-leaktrace-perl libtest-mockobject-perl uglifyjs libdbd-sqlite3-perl libauthen-webauthn-perl libauthen-oath-perl cpanm Authen::U2F Authen::U2F::Tester Crypt::U2F::Server::Simple diff --git a/doc/sources/admin/prereq.rst b/doc/sources/admin/prereq.rst index 0173f9097..469b24c3f 100644 --- a/doc/sources/admin/prereq.rst +++ b/doc/sources/admin/prereq.rst @@ -95,6 +95,8 @@ Second factor - Crypt::U2F::Server::Simple (U2F keys) - Convert::Base32 (TOTP) +- Authen::WebAuthn (FIDO2 WebAuthen) +- Authen::OATH (OTP) Specific authentication backends ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -138,6 +140,7 @@ Unit tests - Authen::U2F::Tester - Crypt::U2F::Server - Test::MockObject +- DBD::SQLite - Test::Output - Test::POD - Time::Fake From 3fc401bf791766eb37469bb38f3078199480e0e9 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Fri, 13 May 2022 00:15:38 +0200 Subject: [PATCH 33/35] Improve doc --- doc/sources/admin/exportedvars.rst | 13 ++++++++++--- doc/sources/admin/portalcustom.rst | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/sources/admin/exportedvars.rst b/doc/sources/admin/exportedvars.rst index 3f0354e7b..fe66bf285 100644 --- a/doc/sources/admin/exportedvars.rst +++ b/doc/sources/admin/exportedvars.rst @@ -51,13 +51,20 @@ portal: - macros are used to extend (or rewrite) :doc:`exported variables`. A macro is stored as attributes: it can contain boolean results or any string -- macros can also be used to import environment variables *(these +- macros can also be used for importing environment variables *(these variables are in CGI format)*. Example: ``$ENV{HTTP_COOKIE}`` - groups are stored as a string with values separated by ''; '' - (default values separator) in the special attribute ``groups``: it - contains the names of groups whose rules were returned true for the + (default multivalues separator) in the special attribute ``groups``: it + contains names of groups whose rules were returned true for the current user. For example: +.. danger:: + + Macros can be used for rewriting or overloading exported variables + but it can lead to some side effects. Be aware of alphabetical order + and keep in mind that exported variables are set. Then macros and + groups are computed. + .. code-block:: perl $groups = group3; admin diff --git a/doc/sources/admin/portalcustom.rst b/doc/sources/admin/portalcustom.rst index 8c100d830..002e27612 100644 --- a/doc/sources/admin/portalcustom.rst +++ b/doc/sources/admin/portalcustom.rst @@ -361,7 +361,7 @@ Password Policy - **Minimal upper characters**: leave 0 to bypass the check - **Minimal digit characters**: leave 0 to bypass the check - **Minimal special characters**: leave 0 to bypass the check -- **Allowed special characters**: set '__ALL__' value to allow ALL special characters. A blanck value forbids ALL special characters (Note that ``_`` is not a special character) +- **Allowed special characters**: set '__ALL__' value to allow ALL special characters. A blank value forbids ALL special characters (Note that ``_`` is not a special character) .. _portalcustom-other-parameters: From 2ea240c25cccaa6f80e5f61c6b3d14acc77daade Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Sun, 15 May 2022 23:58:24 +0200 Subject: [PATCH 34/35] Improve template --- .../site/templates/bootstrap/checkuser.tpl | 136 ++++++++++-------- 1 file changed, 73 insertions(+), 63 deletions(-) diff --git a/lemonldap-ng-portal/site/templates/bootstrap/checkuser.tpl b/lemonldap-ng-portal/site/templates/bootstrap/checkuser.tpl index dfd7f950f..87b7cc056 100644 --- a/lemonldap-ng-portal/site/templates/bootstrap/checkuser.tpl +++ b/lemonldap-ng-portal/site/templates/bootstrap/checkuser.tpl @@ -32,24 +32,65 @@
-
-
HEADERS
-
- - :
-
+
+
+
HEADERS
+
+ + :
+
+
-
- -
-
HISTORY
- + +
+ + +
+
+
SSO GROUPS
+ +
+
+
+
+ + +
+
+ +
MACROS
+ + + + + + + + + + + + + + + +
KeyValue
+
+
+
+ + +
+
+ +
HISTORY
+ -
Success
+
Success
@@ -57,18 +98,18 @@ - - - - - + + + + +
Date Value
">
">
-
- + + -
Failed
+
Failed
@@ -76,32 +117,23 @@ - - - - - + + + + +
Date Value
">
">
+
-
- - -
-
SSO GROUPS
-
- -
-
-
-
-
-
+ + +
+
-
-
ATTRIBUTES
+
ATTRIBUTES
@@ -118,32 +150,10 @@
-
-
-
- -
-
MACROS
- - - - - - - - - - - - - - - -
KeyValue
-
+
From 5a29ce8ffed0339d2ccffee180d0ceb942e80eea Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Mon, 16 May 2022 00:03:35 +0200 Subject: [PATCH 35/35] Update unit tests --- .../t/67-CheckUser-with-Global-token.t | 3 ++- .../t/67-CheckUser-with-Impersonation-and-Macros.t | 4 ++-- lemonldap-ng-portal/t/67-CheckUser-with-token.t | 3 ++- lemonldap-ng-portal/t/67-CheckUser.t | 6 ++++-- lemonldap-ng-portal/t/68-Impersonation-with-TOTP.t | 2 +- .../t/68-Impersonation-with-filtered-merge.t | 8 ++++---- .../t/68-Impersonation-with-merge.t | 14 +++++++------- 7 files changed, 22 insertions(+), 18 deletions(-) diff --git a/lemonldap-ng-portal/t/67-CheckUser-with-Global-token.t b/lemonldap-ng-portal/t/67-CheckUser-with-Global-token.t index 0dc0d00f3..611aef8ff 100644 --- a/lemonldap-ng-portal/t/67-CheckUser-with-Global-token.t +++ b/lemonldap-ng-portal/t/67-CheckUser-with-Global-token.t @@ -166,7 +166,8 @@ ok( $res->[2]->[0] =~ m%Auth-User: %, 'Found Auth-User' ) or explain( $res->[2]->[0], 'Header Key: Auth-User' ); ok( $res->[2]->[0] =~ m%: rtyler
%, 'Found rtyler' ) or explain( $res->[2]->[0], 'Header Value: rtyler' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) +ok( $res->[2]->[0] =~ m%
su
%, + 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); ok( $res->[2]->[0] =~ m%uid%, 'Found uid' ) or explain( $res->[2]->[0], 'Attribute Value uid' ); diff --git a/lemonldap-ng-portal/t/67-CheckUser-with-Impersonation-and-Macros.t b/lemonldap-ng-portal/t/67-CheckUser-with-Impersonation-and-Macros.t index ec7301e64..50980055d 100644 --- a/lemonldap-ng-portal/t/67-CheckUser-with-Impersonation-and-Macros.t +++ b/lemonldap-ng-portal/t/67-CheckUser-with-Impersonation-and-Macros.t @@ -186,10 +186,10 @@ ok( $res->[2]->[0] =~ m%Macro_1%, 'Found uid' ) ok( $nbr = ( $res->[2]->[0] =~ s%Macro_1%%g ), 'Found two well computed macros' ) or explain( $res->[2]->[0], 'Macros not well computed' ); -ok( $res->[2]->[0] =~ m%
authGroup
%, +ok( $res->[2]->[0] =~ m%
authGroup
%, 'Found group "authGroup"' ) or explain( $res->[2]->[0], 'Group "authgroup"' ); -ok( $res->[2]->[0] =~ m%
realAuthGroup
%, +ok( $res->[2]->[0] =~ m%
realAuthGroup
%, 'Found group "realAuthGroup"' ) or explain( $res->[2]->[0], 'Found group "realAuthGroup"' ); count(7); diff --git a/lemonldap-ng-portal/t/67-CheckUser-with-token.t b/lemonldap-ng-portal/t/67-CheckUser-with-token.t index fc32f3265..e0fe3e118 100644 --- a/lemonldap-ng-portal/t/67-CheckUser-with-token.t +++ b/lemonldap-ng-portal/t/67-CheckUser-with-token.t @@ -166,7 +166,8 @@ ok( $res->[2]->[0] !~ m%emptyHeader: %, 'emptyHeader not found' ) or explain( $res->[2]->[0], 'Header Key: emptyHeader' ); ok( $res->[2]->[0] =~ m%: rtyler%, 'Found rtyler' ) or explain( $res->[2]->[0], 'Header Value: rtyler' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) +ok( $res->[2]->[0] =~ m%
su
%, + 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); ok( $res->[2]->[0] =~ m%uid%, 'Found uid' ) or explain( $res->[2]->[0], 'Attribute Value uid' ); diff --git a/lemonldap-ng-portal/t/67-CheckUser.t b/lemonldap-ng-portal/t/67-CheckUser.t index 6f6cc8319..e28e173bd 100644 --- a/lemonldap-ng-portal/t/67-CheckUser.t +++ b/lemonldap-ng-portal/t/67-CheckUser.t @@ -429,7 +429,8 @@ ok( $res->[2]->[0] =~ m%Auth-User: %, 'Found Auth-User' ) or explain( $res->[2]->[0], 'Header Key: Auth-User' ); ok( $res->[2]->[0] =~ m%: rtyler
%, 'Found rtyler' ) or explain( $res->[2]->[0], 'Header Value: rtyler' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) +ok( $res->[2]->[0] =~ m%
su
%, + 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); ok( $res->[2]->[0] =~ m%uid%, 'Found uid' ) or explain( $res->[2]->[0], 'Attribute Value uid' ); @@ -489,7 +490,8 @@ ok( $res->[2]->[0] =~ m%Auth-User: %, 'Found Auth-User' ) or explain( $res->[2]->[0], 'Header Key: Auth-User' ); ok( $res->[2]->[0] =~ m%: rtyler
%, 'Found rtyler' ) or explain( $res->[2]->[0], 'Header Value: rtyler' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) +ok( $res->[2]->[0] =~ m%
su
%, + 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); ok( $res->[2]->[0] =~ m%uid%, 'Found uid' ) or explain( $res->[2]->[0], 'Attribute Value uid' ); diff --git a/lemonldap-ng-portal/t/68-Impersonation-with-TOTP.t b/lemonldap-ng-portal/t/68-Impersonation-with-TOTP.t index 013743fc4..ea4863174 100644 --- a/lemonldap-ng-portal/t/68-Impersonation-with-TOTP.t +++ b/lemonldap-ng-portal/t/68-Impersonation-with-TOTP.t @@ -226,7 +226,7 @@ m%
su
%, 'Found su' ) + ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); ok( $res->[2]->[0] =~ m%uid%, 'Found uid' ) or explain( $res->[2]->[0], 'Attribute Value uid' ); diff --git a/lemonldap-ng-portal/t/68-Impersonation-with-filtered-merge.t b/lemonldap-ng-portal/t/68-Impersonation-with-filtered-merge.t index 8ffdec23e..1e14f0b71 100644 --- a/lemonldap-ng-portal/t/68-Impersonation-with-filtered-merge.t +++ b/lemonldap-ng-portal/t/68-Impersonation-with-filtered-merge.t @@ -127,13 +127,13 @@ ok( $res->[2]->[0] =~ m%Auth-User: %, 'Found Auth-User' ) or explain( $res->[2]->[0], 'Header Key: Auth-User' ); ok( $res->[2]->[0] =~ m%: dwho
%, 'Found dwho' ) or explain( $res->[2]->[0], 'Header Value: dwho' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) +ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); -ok( $res->[2]->[0] =~ m%
su_test
%, 'Found su_test' ) +ok( $res->[2]->[0] =~ m%
su_test
%, 'Found su_test' ) or explain( $res->[2]->[0], 'SSO Groups: su_test' ); -ok( $res->[2]->[0] !~ m%
_test_
%, 'NOT found _test_' ) +ok( $res->[2]->[0] !~ m%
_test_
%, 'NOT found _test_' ) or explain( $res->[2]->[0], 'SSO Groups: _test_' ); -ok( $res->[2]->[0] !~ m%
test_su%, 'NOT found test_su' ) +ok( $res->[2]->[0] !~ m%
test_su%, 'NOT found test_su' ) or explain( $res->[2]->[0], 'SSO Groups: test_su' ); ok( $res->[2]->[0] =~ m%uid%, 'Found uid' ) or explain( $res->[2]->[0], 'Attribute Value uid' ); diff --git a/lemonldap-ng-portal/t/68-Impersonation-with-merge.t b/lemonldap-ng-portal/t/68-Impersonation-with-merge.t index 53d454dfc..4f7f6292e 100644 --- a/lemonldap-ng-portal/t/68-Impersonation-with-merge.t +++ b/lemonldap-ng-portal/t/68-Impersonation-with-merge.t @@ -116,12 +116,12 @@ ok( $res->[2]->[0] =~ m%%, 'Found trspan="headers"' ) ok( $res->[2]->[0] =~ m%%, 'Found trspan="groups_sso"' ) or explain( $res->[2]->[0], 'trspan="groups_sso"' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found SSO group "su"' ) +ok( $res->[2]->[0] =~ m%
su
%, 'Found SSO group "su"' ) or explain( $res->[2]->[0], 'Found SSO group "su"' ); -ok( $res->[2]->[0] =~ m%
su_test
%, +ok( $res->[2]->[0] =~ m%
su_test
%, 'Found SSO group "su_test"' ) or explain( $res->[2]->[0], 'Found SSO group "su_test"' ); -ok( $res->[2]->[0] =~ m%
test_su
%, +ok( $res->[2]->[0] =~ m%
test_su
%, 'Found SSO group "test_su"' ) or explain( $res->[2]->[0], 'Found SSO group "test_su"' ); ok( $res->[2]->[0] =~ m%%, @@ -135,13 +135,13 @@ ok( $res->[2]->[0] =~ m%Auth-User: %, 'Found Auth-User' ) or explain( $res->[2]->[0], 'Header Key: Auth-User' ); ok( $res->[2]->[0] =~ m%: dwho
%, 'Found dwho' ) or explain( $res->[2]->[0], 'Header Value: dwho' ); -ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) +ok( $res->[2]->[0] =~ m%
su
%, 'Found su' ) or explain( $res->[2]->[0], 'SSO Groups: su' ); -ok( $res->[2]->[0] =~ m%
su_test
%, 'Found su_test' ) +ok( $res->[2]->[0] =~ m%
su_test
%, 'Found su_test' ) or explain( $res->[2]->[0], 'SSO Groups: su_test' ); -ok( $res->[2]->[0] !~ m%
_test_
%, 'NOT found _test_' ) +ok( $res->[2]->[0] !~ m%
_test_
%, 'NOT found _test_' ) or explain( $res->[2]->[0], 'SSO Groups: _test_' ); -ok( $res->[2]->[0] =~ m%
test_su
%, 'Found test_su' ) +ok( $res->[2]->[0] =~ m%
test_su
%, 'Found test_su' ) or explain( $res->[2]->[0], 'SSO Groups: test_su' ); ok( $res->[2]->[0] =~ m%_whatToTrace%, 'Found _whatToTrace' )