lemonldap-ng issueshttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues2024-03-27T13:29:12Zhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3127Support SAML subject-id and pairwise-id natively2024-03-27T13:29:12ZMaxime BessonSupport SAML subject-id and pairwise-id nativelysubject-id and pairwise-id are replacement for SAML NameIDs in use in Renater/Edugain federations :
https://docs.oasis-open.org/security/saml-subject-id-attr/v1.0/cs01/saml-subject-id-attr-v1.0-cs01.html
Currently, subject-id and pairwi...subject-id and pairwise-id are replacement for SAML NameIDs in use in Renater/Edugain federations :
https://docs.oasis-open.org/security/saml-subject-id-attr/v1.0/cs01/saml-subject-id-attr-v1.0-cs01.html
Currently, subject-id and pairwise-id can be enabled via a macro, but this is complex to configure. Especially pairwise-id which must be configured as a per-SP macro for all SPs
Maybe we should natively implement subject-id and pairwise-id through simple options in SAML SP configs2.20.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3126Allow multiple TOTP devices to be registered2024-03-27T10:11:12ZMaxime BessonAllow multiple TOTP devices to be registered### Summary
Currently it is possible to register multiple Webauthn devices, but not multiple TOTP### Summary
Currently it is possible to register multiple Webauthn devices, but not multiple TOTP2.20.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3125Add base class for "reset password by SMS"2024-03-27T10:22:31ZYaddAdd base class for "reset password by SMS"SMS API are not standard, however we could easily have a base class to prepare that.
## Design proposition
* Move part of [MailPasswordReset](lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm) into "Lib/PasswordR...SMS API are not standard, however we could easily have a base class to prepare that.
## Design proposition
* Move part of [MailPasswordReset](lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm) into "Lib/PasswordReset.pm"
* Maybe create a "Lib/SMSBase.pm" that stores custom parameters somewhere and just needs a "sendSMS" method in sub classes
* Create a "Lib/SMS.pm" that requires a class that exposes a `sendSMS($phone, $text)`
* Create a "Plugins/SMSPasswordResetBase.pm" that inherits from "Lib/PasswordReset.pm" and uses "Lib/SMS.pm"2.20.0YaddYaddhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3124Allow users to configure WebAuthn relying party ID2024-03-20T13:29:26ZMaxime BessonAllow users to configure WebAuthn relying party ID### Summary
Some users want to use an external system to register WebAuthn credentials
This requires a given WebAuthn device to share credentials between the portal and the registration system
### Design proposition
Allow the RP ID t...### Summary
Some users want to use an external system to register WebAuthn credentials
This requires a given WebAuthn device to share credentials between the portal and the registration system
### Design proposition
Allow the RP ID to be configured in 2F::WebAuthn2.19.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3123JWKS timeout is not implemented2024-03-27T10:40:19ZMaxime BessonJWKS timeout is not implemented### Affected version
Version: 2.18.2
### Summary
* Configure Auth::OpenIDConnect with a test OP
* set oidcOPMetaDataOptionsJWKSTimeout = 30 (or any non zero value)
* When restarting portal, JWKS is downloaded :white_check_mark:
* Aft...### Affected version
Version: 2.18.2
### Summary
* Configure Auth::OpenIDConnect with a test OP
* set oidcOPMetaDataOptionsJWKSTimeout = 30 (or any non zero value)
* When restarting portal, JWKS is downloaded :white_check_mark:
* After 30 seconds, JWKS is not refreshed :x:2.19.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3122Random DB errors when using llng-fastcgi-server in foreground mode2024-03-27T09:37:24ZMaxime BessonRandom DB errors when using llng-fastcgi-server in foreground mode### Affected version
Version: 2.18.2
Platform: FastCGI server with the coudot/lemonldap-ng docker image
### Summary
* I have customized the coudot/lemonldap-ng image to use CDBI with a mariadb server
* I encounter difficult to predic...### Affected version
Version: 2.18.2
Platform: FastCGI server with the coudot/lemonldap-ng docker image
### Summary
* I have customized the coudot/lemonldap-ng image to use CDBI with a mariadb server
* I encounter difficult to predict DB errors
* Errors can be easily triggered with high load and a disabled configuration cache
### Logs
Some of the errors that pop up:
```
DBD::mysql::db selectrow_array failed: Unknown or undefined error code
...
DBD::mysql::db selectrow_arrayref failed: fetch() without execute()
```
### Root cause
llng-fastcgi-server instanciates a handler[](https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/blob/v2.18.2/fastcgi-server/sbin/llng-fastcgi-server?ref_type=tags#L121) during startup.
This is needed to have shared status (apparently). But this action causes DBI to cache a connection to the database.
This connection cache is preserved after the process are forked by
* Plack startup (only when --foreground is not set)
* The FastCGI process manager (NPROC worker processes)
During the plack startup fork, the parent process exists, which runs DBI cleanup and closes the file descriptor, therefore invalidating the cache in other processes.
When --foreground is set, the file descriptor remains open and is reused until:
* That shared connection is closed by the SQL server
* One of the process terminates
### Possible fixes
Either:
* Revert 019f1e75e829ec9fdfc34d23e2874398a5cba8f0 and find another way to share the status server
* Find another way to have working docker logs without --foreground, and remove this option
* Fork llng-fastcgi-server one more time before handing control to Plack2.20.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3121LLNG should not fail when local cache is broken2024-03-27T09:08:38ZYaddLLNG should not fail when local cache is broken2.19.0YaddYaddhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3120Add unique HTTP request ID to logs2024-03-12T15:12:18ZMaxime BessonAdd unique HTTP request ID to logs### Summary
Having a unique identifier for a HTTP request is a precious debugging tool.
There are some existing tools for this:
* Apache ``UNIQUE_ID``
* Nginx ``$request_id``
* ``X-Request-ID``, ``X-Correlation-ID`` etc.
### Design pr...### Summary
Having a unique identifier for a HTTP request is a precious debugging tool.
There are some existing tools for this:
* Apache ``UNIQUE_ID``
* Nginx ``$request_id``
* ``X-Request-ID``, ``X-Correlation-ID`` etc.
### Design proposition
* Extend the request object with a new ``$req->request_id`` field populated from one of the previously mentionned sources
* Auto-generate a request_id if one isn't found
* Document how to easily enable ``request_id`` in logs2.19.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3119Inconsistent logs when using "faketicket" CAS access policy2024-03-08T15:03:36ZMaxime BessonInconsistent logs when using "faketicket" CAS access policy### Affected version
Version: 2.18.2
### Summary
* Configure CAS Access control policy = Fake ticket
* Set an access rule for a CAS service
### Logs
When accessing with an unauthorized user:
```
[warn] User dwho is not authorized t...### Affected version
Version: 2.18.2
### Summary
* Configure CAS Access control policy = Fake ticket
* Set an access rule for a CAS service
### Logs
When accessing with an unauthorized user:
```
[warn] User dwho is not authorized to access to testcasapp
[notice] User dwho is authorized to access to testcasapp
```
Logs are contradictory2.19.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3118Minimal LDAP server load-balancing2024-03-08T14:10:26ZYaddMinimal LDAP server load-balancing[Net::LDAP](https://metacpan.org/pod/Net::LDAP) provide a way to have more than one LDAP server, this permits to have a fallback. However it tries servers always in the same order. This has some issues:
- only one server is used
- when...[Net::LDAP](https://metacpan.org/pod/Net::LDAP) provide a way to have more than one LDAP server, this permits to have a fallback. However it tries servers always in the same order. This has some issues:
- only one server is used
- when the first server is down, all LDAP connections are slowed down to wait for first failure
# Design proposition
This should be pushed to [Lemonldap::NG::Portal::Lib::Net::LDAP](lemonldap-ng-portal/blib/lib/Lemonldap/NG/Portal/Lib/Net/LDAP.pm) and [Apache::Session::Browseable](https://metacpan.org/pod/Apache::Session::Browseable).
```perl
our %knownDown;
our %knownLdapServerStrings;
sub sortDead {
return 1 if $knownDown{$a} and !$knownDown{$b};
return -1 if $knownDown{$b} and !$knownDown{$a};
return 0;
}
# ...
sub new {
# ...
$knownLdapServerStrings{$conf->ldapServer} ||= [ split( /\s+/, $conf->ldapServer ) || 'localhost' ];
# Simple round-robbin if asked
if ($conf->{ldapRoundRobbin}) {
my $last = shift @{ $knownLdapServerStrings{$conf->ldapServer} };
push @{ $knownLdapServerStrings{$conf->ldapServer} }, $last;
}
# Push server which have failed to the end of the list
my @uris = sort pushDeadToEnd @uris;
my $first = $uris[0];
# ... create LDAP object using \@uris
# Update knownDone list:
# The server chosen by Net::LDAP is up
delete $knownDown{ $self->{net_ldap_uri} };
# If Net::LDAP changed, this means that first LDAP is down
if ( $self->{net_ldap_uri} != $first ) {
$knownDown{ $first } = 1;
}
# ...
}
```
@clement_oudot, @maxbes: what do you think ?In discussionYaddYaddhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3117Add a hook before 2fa retry2024-03-08T10:17:50ZMaxime BessonAdd a hook before 2fa retryWe added the possibility to retry a second factor in #3080
It could be useful to run some custom code (eg for reporting) right before the 2FA is retriedWe added the possibility to retry a second factor in #3080
It could be useful to run some custom code (eg for reporting) right before the 2FA is retried2.19.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3116Restart authentication process when error is linked to token expiration2024-03-27T10:59:00ZClément OUDOTRestart authentication process when error is linked to token expirationCurrently, when the security token is expired (`Returned error: 82 (PE_TOKENEXPIRED)`), we end up on error page and user must return to portal to restart authentication process.
It could be better to display the error on the login form ...Currently, when the security token is expired (`Returned error: 82 (PE_TOKENEXPIRED)`), we end up on error page and user must return to portal to restart authentication process.
It could be better to display the error on the login form so user can directly restart the authentication process.2.20.0https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3115Date in login history is based on session _utime, not the very same time as t...2024-03-27T09:53:05Zphilippe lhardyphilha@worteks.comDate in login history is based on session _utime, not the very same time as the login triggering action### Affected version
All versions up to 2.18 and including current dev.
### Summary
Success or Failure records for login history use _utime and not actual time of action.
This is enlighted when using 2FA.
When tentatively implementi...### Affected version
All versions up to 2.18 and including current dev.
### Summary
Success or Failure records for login history use _utime and not actual time of action.
This is enlighted when using 2FA.
When tentatively implementing #3106 ordering of login failure of multiple successive 2FA failure couldn't be based on time since all entries had the very same one.
### Possible fixes
Use current time within loging history.2.19.0philippe lhardyphilha@worteks.comphilippe lhardyphilha@worteks.comhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3114Different handling for utf-8 in http header and perl variables2024-03-06T09:50:14ZBenjamin DemarteauDifferent handling for utf-8 in http header and perl variables### Affected version
Version:
```
$ rpm -qv lemonldap-ng httpd
lemonldap-ng-2.18.2-1.el8.noarch
httpd-2.4.37-62.module+el8.9.0+1436+2b7d5021.x86_64
$ cat /etc/rocky-release
Rocky Linux release 8.9 (Green Obsidian)
```
Platform: Apach...### Affected version
Version:
```
$ rpm -qv lemonldap-ng httpd
lemonldap-ng-2.18.2-1.el8.noarch
httpd-2.4.37-62.module+el8.9.0+1436+2b7d5021.x86_64
$ cat /etc/rocky-release
Rocky Linux release 8.9 (Green Obsidian)
```
Platform: Apache HTTPD
### Summary
We are seeing different handling depending on where the information was encoded. When adding utf-8 variables through the manager and the variables fetched from LDAP.
### Logs
Couldn't find logs relevant to this problem (none on login on display of test1 vhost).
### Backends used
Using
```yml
globalStorage: Apache::Session::Browseable::LDAP
globalStorageOptions: |-
{ \
'type' => 'LDAP', \
'ldapServer' => 'ldap+tls://{{ ldap_host }}', \
'ldapConfBase' => 'ou=sessions,ou=lemonldap,ou=appconfig,dc=liege,dc=be', \
'ldapBindDN' => 'cn=lemonldap-{{ inventory_hostname }},ou=technical,ou=people,dc=liege,dc=be', \
'ldapBindPassword' => '{{ lemonldap_ldap_password }}', \
'ldapObjectClass' => 'applicationProcess', \
'ldapAttributeId' => 'cn', \
'ldapAttributeContent' => 'description', \
'ldapAttributeIndex' => 'ou', \
'ldapRaw' => '(?i:^jpegPhoto|;binary)', \
'Index' => '_whatToTrace _session_kind _assert_id' \
}
```
### Details
We see different handling of encoding depending of where the strings are coming from:
With a user coming from LDAP (fully utf-8) with name "Fiçà3" and values exported to the test1 vhost as such:
![image](/uploads/e7f00844e89331004d0f77be5b967b1e/image.png)
We get in headers:
![image](/uploads/a4459cf35dfc259e4024b51011aea665/image.png)
In perl variables:
![image](/uploads/c5a8820b86199237c0ac8461bb9b34ef/image.png)
In the manager's session viewer:
![image](/uploads/4430457f675cf2df571ba8673be0d982/image.png)
We do not expect http headers to be encoded as utf-8, but we do expect utf-8 strings to be encoded the same no matter where they come from.
We also made sure to set `ldapRaw` so that the perl ldap module recognizes fields as utf-8.https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3113Add possibility to store conf secrets in separated files2024-03-27T09:09:10ZYaddAdd possibility to store conf secrets in separated filesWhen I'm using Lemonldap with static configuration (deployed using help chart), the key rotation maybe lost when restarting containers.
## Design proposition
`lemonldap-ng.ini` contains a new key `secretsPath`. Then when [Common::Conf]...When I'm using Lemonldap with static configuration (deployed using help chart), the key rotation maybe lost when restarting containers.
## Design proposition
`lemonldap-ng.ini` contains a new key `secretsPath`. Then when [Common::Conf](lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm) see that:
- when "load": read the list of secret and launches them from this directory (keyName == fileName)
- when "store": ignore this changes ?
@clement_oudot, @maxbes, @xavierb : any idea/advice ?2.19.0YaddYaddhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3112Configuration override from lemonldap-ng.ini can be lost due to cache issues2024-03-27T09:41:40ZMaxime BessonConfiguration override from lemonldap-ng.ini can be lost due to cache issues### Affected version
Version: 2.18.2
### Summary
This bug is easier to reproduce with a separate handler and portal, but happens with all configurations
* Configure a remote handler with globalStorage=REST
* Access the handler a few ...### Affected version
Version: 2.18.2
### Summary
This bug is easier to reproduce with a separate handler and portal, but happens with all configurations
* Configure a remote handler with globalStorage=REST
* Access the handler a few times => overrides are applied
* Save a new configuration on the portal, without triggering a configuration reload (reloadUrls) on the remote handler
* On the remote handler, wait for configuration cache to expire
* On the remote handler, run purgeCentralCache/purgeLocalCache (! AS WWW-DATA/APACHE! )
* Access the remote handler again => globalStorage is lost
### Logs
Before cache expiration:
```
[debug] Check configuration for Lemonldap::NG::Handler::Server::Main
[debug] Get configuration from cache without verification.
```
cache content:
```
globalStorage='Lemonldap::NG::Common::Apache::Session::REST'
```
Cache contains conf from DB + INI overrides
Publish a new version, wait for cache to expire, run purgeCentralCache (as www-data)
cache content:
```
globalStorage='Apache::Session::File'
```
Cache contains conf from DB without overrides
Try to access the handler
```
[debug] Check configuration for Lemonldap::NG::Handler::Server::Main
[debug] Get configuration from cache without verification.
[debug] Get configuration 448 aged 1709392350
[info] Loading configuration 448 for process 77060
```
Configuration is loaded from (incorrect) cache, new version is found, and Handler is reloaded from this new version that doesn't have INI overrides
Later:
```
[info] Session cannot be tied: unexistant session xxx at /usr/share/perl5/Apache/Session/Store/File.pm
```
### Possible fixes
This is a subtle bug but I have hit many different versions of it over the years:
* checkTime being reset from 1 to default of 600
* globalStorage being randomly lost on remote handler
* etc
This bug comes from the fact that Common::Conf stores INI overrides in the config cache. IMO this is a bad idea. The cache, which is shared by *all* LLNG processes on the machine, should only contain DB conf, and overrides should be applied on top of it.
This behavior also means that it's also impossible to have a config override be different for two components, such as:
```
[portal]
globalStorage=Apache::Session::File
[handler]
globalStorage=Lemonldap::NG::Common::Apache::Session::REST
```2.19.0Maxime BessonMaxime Bessonhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3111Hide Code2F secrets even from debug logs2024-03-27T10:25:25ZMaxime BessonHide Code2F secrets even from debug logsCurrently, secrets such as OTP codes (Code2F.pm) are displayed in cleartext in debug logs.
This is useful for debugging
Some users want to be able to hide the values even from error logs
We should find a way to do this, maybe a special ...Currently, secrets such as OTP codes (Code2F.pm) are displayed in cleartext in debug logs.
This is useful for debugging
Some users want to be able to hide the values even from error logs
We should find a way to do this, maybe a special value in hiddenAttributes ?2.19.0Clément OUDOTClément OUDOThttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3110_2fDevices redaction corrupts session2024-03-27T10:45:57ZDaniel Berteaud_2fDevices redaction corrupts session### Affected version
Version: 2.18.2
Platform: Alma Linux 9, custom Docker image (using the RPMS from https://lemonldap-ng.org/redhat/stable/)
### Summary
Active Directory grants an auth level of 2, and some apps require an auth leve...### Affected version
Version: 2.18.2
Platform: Alma Linux 9, custom Docker image (using the RPMS from https://lemonldap-ng.org/redhat/stable/)
### Summary
Active Directory grants an auth level of 2, and some apps require an auth level of 5. The Upgrade Session plugins handles the re-auth with a second factor (WebAuthn and TOTP are configured). While this is working, I sometime have a corrupted session. The issue comes from the \_2fDevices, which looks like
```plaintext
"_2fDevices": "******"
```
As LL::NG is expecting a JSON array, this is breaking. The session can neither be displayed in the manager, nor can it be upgraded with 2FA. If I try to access a app which requires an authLevel of 5, I just get a white page with "Internal Server Error" instead of the 2FA upgrade page on the portal.
### Logs
```plaintext
[Wed Feb 28 10:04:12 2024] [LLNG:655] [warn] User rejected due to insufficient authentication level
[Wed Feb 28 10:04:12 2024] [LLNG:655] [warn] -> Session upgrade enabled
[Wed Feb 28 10:04:12 2024] [LLNG:655] [error] Corrupted session (_2fDevices): malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "******") at /usr/share/perl5/vendor_perl/JSON.pm line 190.
[uwsgi-perl error] Can't use an undefined value as an ARRAY reference at /usr/share/perl5/vendor_perl/Lemonldap/NG/Portal/2F/Engines/Default.pm line 305.
[Wed Feb 28 10:04:54 2024] [LLNG:41] [error] Corrupted session (_2fDevices): malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "******") at /usr/share/perl5/vendor_perl/JSON.pm line 190.
[uwsgi-perl error] Can't use an undefined value as an ARRAY reference at /usr/share/perl5/vendor_perl/Lemonldap/NG/Portal/2F/Engines/Default.pm line 305.
```
### Backends used
uwsgi and nginx for the portal and manager, Traefik and uwsgi for the Handler, postgres for configuration and sessions, Active Directory (samba4) for UserDB and PasswordDB. Handlers are using the REST API for config and session. I think the issue comes from here. 2fDevices is an hidden attribute (don't know where this is configured yet). I've enabled "Export secrets attributes" on the REST server, but it doesn't look like it changes anything. As the handler gets a "\*\*\*\*\*\*\*" from the REST API for the session, when it updates the session, it corrupts it in the session database. Attribute redaction should honor attribute type (eg, set 2fDevices as \["\*\*\*\*\*"\] instead of "\*\*\*\*\*") so at least the session wouldn't be corrupted. I also need to find how to remove 2fDevices from the hidden attribute list so it can be served to my handlers with the REST API, but this is probably just a matter of correct configuration.2.20.0https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3109Conf test: should warn when auth is Choice and userDB isn't set to Choice or ...2024-03-27T10:54:34ZYaddConf test: should warn when auth is Choice and userDB isn't set to Choice or SameNot an error but often a mistakeNot an error but often a mistake2.19.0YaddYaddhttps://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/3108Digest::HMAC should be a required dependency2024-03-11T13:27:24ZMaxime BessonDigest::HMAC should be a required dependency### Affected version
Version: 2.18.2
### Summary
* Install LLNG on Centos8 without recommended dependencies
* Portal doesn't start
### Logs
```
Lemonldap::NG::Portal::Plugins::TrustedBrowser load error: Could not load class (Lemonl...### Affected version
Version: 2.18.2
### Summary
* Install LLNG on Centos8 without recommended dependencies
* Portal doesn't start
### Logs
```
Lemonldap::NG::Portal::Plugins::TrustedBrowser load error: Could not load class (Lemonldap::NG::Common::TOTP) because : Can't locate Digest/HMAC_SHA1.pm in @INC
```
### Possible fixes
* Do not load TrustedBrowser by default
* OR: make Digest::HMAC a required dependency: probably makes more sense because TOTP is common these days2.19.0Maxime BessonMaxime Besson