Merge branch 'v2.0'

This commit is contained in:
Yadd 2021-03-24 10:09:03 +01:00
commit f56fd636fe
443 changed files with 14733 additions and 32645 deletions

2
.ctags Normal file
View File

@ -0,0 +1,2 @@
--exclude=*/blib/*
--exclude=*.js

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
.gitignore
.vstags
tags
doc/sources/admin/_build/
doc/pages/documentation/
e2e-tests/conf

View File

@ -1,15 +1,26 @@
.build_job: &job_build
.build_job:
stage: build
script:
- apt-get update && apt-get -y dist-upgrade
# Workaround for bionic
- DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata
- ci-build-pkg
retry: 1
artifacts:
expire_in: 1 hour
paths:
- result/*
except:
variables:
- $SONARJOB == "1"
.debian_build_job:
extends: .build_job
script:
- apt-get update && apt-get -y dist-upgrade
- DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata
- ci-build-pkg
before_script:
- env | grep ^CI_
# Converting to native package...
- sed -i "1{s/-1) /$suffix) /}" debian/changelog
- sed -i "1{s/-2) /$suffix) /}" debian/changelog
- sed -i 's/3.0 (quilt)/3.0 (native)/' debian/source/format
stages:
- build
@ -18,10 +29,6 @@ stages:
before_script:
- env | grep ^CI_
# Converting to native package...
- sed -i "1{s/-1) /$suffix) /}" debian/changelog
- sed -i "1{s/-2) /$suffix) /}" debian/changelog
- sed -i 's/3.0 (quilt)/3.0 (native)/' debian/source/format
autopkgtest:
stage: build
@ -34,47 +41,40 @@ autopkgtest:
- make -j8 autopkgtest
build_stretch:
extends: .debian_build_job
image: buildpkg/debian:stretch
<<: *job_build
build_buster:
extends: .debian_build_job
image: buildpkg/debian:buster
<<: *job_build
build_disco:
image: buildpkg/ubuntu:disco
<<: *job_build
#build_xenial:
# extends: .debian_build_job
# image: buildpkg/ubuntu:xenial
# <<: *job_build
build_bionic:
extends: .debian_build_job
image: buildpkg/ubuntu:bionic
<<: *job_build
build_centos_7:
extends: .build_job
image: buildpkg/centos:7
stage: build
script:
- rm -f /etc/yum.repos.d/CentOS-Sources.repo
- yum -y install epel-release
- make rpm-dist
- ci-build-pkg
artifacts:
expire_in: 1 day
paths:
- result/*
build_centos_8:
extends: .build_job
image: buildpkg/centos:8
stage: build
script:
- yum-config-manager --enable PowerTools
- yum-config-manager --enable AppStream
- yum -y install epel-release
- make rpm-dist
- ci-build-pkg
artifacts:
expire_in: 1 day
paths:
- result/*
sign:
image: buildpkg/debian:stretch
@ -123,3 +123,25 @@ pages:
only:
- master
sonar-inspect:
image: buildpkg/debian:buster
stage: build
script:
- scripts/sonar
artifacts:
expire_in: 1 hour
paths:
- lemonldap-ng-*/cover_db/sonar_generic.xml
- lemonldap-ng-*/perlcritic_report.txt
only:
variables:
- $SONARJOB == "1"
sonar-upload:
stage: deploy
image: sonarsource/sonar-scanner-cli
script:
- sonar-scanner
only:
variables:
- $SONARJOB == "1"

View File

@ -1,6 +1,5 @@
LemonLDAP::NG Core team:
* Maxime BESSON
* David COUTADEUR
* Xavier GUIMARD
* Christophe MAUDOUX
* Clément OUDOT
@ -10,9 +9,10 @@ Past and present contributors:
* Casimir ANTUNES
* Sébastien BAHLOUL
* Oliver BOIREAU
* Jean-Thomas CHECCO
* Sandro CAZZANIGA
* Jean-Thomas CHECCO
* Thomas CHEMINEAU
* David COUTADEUR
* François-Xavier DELTOMBE
* Sebastien DIAZ
* Soisik FROGIER

23
RELEASE
View File

@ -5,7 +5,7 @@ The version
-----------
- The release version should be updated in the following location:
* changelog (add a changelog from GitLab for the target version)
* changelog: change version in scripts/generate-changelog.pl and run it
* Main modules (Common.pm/Handler.pm/Portal.pm/Manager.pm)
* Makefile.PL for cross-dependencies
@ -90,18 +90,21 @@ Upload dist and bundles on sftp://release-up.ow2.org/projects/lemonldap
- RPM: see rpm/REDAME
- DEB:
The DEB repository is hosted on http://lemonldap-ng.org/deb
The DEB repository is hosted on https://lemonldap-ng.org/deb
Copy all generated files (*.deb):
$ scp *.deb lemonldapng@lemonldap-ng.org:incoming/
$ scp *.deb lemonldap-ng@lemonldap-ng.org:incoming/
Then connect on the server and launch reprepro:
$ ssh lemonldapng@lemonldap-ng.org
lemonldapng@lemonldap-ng.org$ cd deb/
lemonldapng@sd-22107:~/deb$ reprepro --ask-passphrase -Vb . includedeb stable ../incoming/*VERSION*deb
lemonldapng@sd-22107:~/deb$ reprepro --ask-passphrase -Vb . includedeb 2.0 ../incoming/*VERSION*deb
On the server, add packages is the appropriate repository, for example:
$ aptly repo add 2.0 incoming/*
$ aptly repo add stable incoming/*
See also reprepro configuration file: 'distributions'
Publish repositories:
$ aptly publish update -gpg-key="57144D2148DD706967DBFF7C548B17BF81F18E7A" 2.0
$ aptly publish update -gpg-key="57144D2148DD706967DBFF7C548B17BF81F18E7A" stable
Remove files from incoming directory:
$ rm incoming/*
- Docker:
Build a new image from https://github.com/LemonLDAPNG/lemonldap-ng-docker
@ -120,7 +123,7 @@ Spread the word
- News on OW2 projects page: https://projects.ow2.org/bin/view/lemonldap-ng/
- Twitter account / Facebook page
- IRC channel subject and Mattermost
- IRC channel subject and OW2 Rocket.Chat channel
- Mailing lists: lemonldap-ng-users / lemonldap-ng-announces
- Optional: blogs and news sites (LinuxFR, etc.)

View File

@ -28,6 +28,21 @@
auth_request_set $headervalue14 $upstream_http_headervalue14;
auth_request_set $headername15 $upstream_http_headername15;
auth_request_set $headervalue15 $upstream_http_headervalue15;
auth_request_set $deleteheader1 $upstream_http_deleteheader1;
auth_request_set $deleteheader2 $upstream_http_deleteheader2;
auth_request_set $deleteheader3 $upstream_http_deleteheader3;
auth_request_set $deleteheader4 $upstream_http_deleteheader4;
auth_request_set $deleteheader5 $upstream_http_deleteheader5;
auth_request_set $deleteheader6 $upstream_http_deleteheader6;
auth_request_set $deleteheader7 $upstream_http_deleteheader7;
auth_request_set $deleteheader8 $upstream_http_deleteheader8;
auth_request_set $deleteheader9 $upstream_http_deleteheader9;
auth_request_set $deleteheader10 $upstream_http_deleteheader10;
auth_request_set $deleteheader11 $upstream_http_deleteheader11;
auth_request_set $deleteheader12 $upstream_http_deleteheader12;
auth_request_set $deleteheader13 $upstream_http_deleteheader13;
auth_request_set $deleteheader14 $upstream_http_deleteheader14;
auth_request_set $deleteheader15 $upstream_http_deleteheader15;
auth_request_set $lmcookie $upstream_http_cookie;
access_by_lua '
local i = 1
@ -38,7 +53,16 @@
else
break
end
i = i +1
i = i + 1
end
i = 1
while true do
if ngx.var["deleteheader"..i] ~= nil then
ngx.req.clear_header(ngx.var["deleteheader"..i])
else
break
end
i = i + 1
end
';

129
changelog
View File

@ -1,3 +1,132 @@
lemonldap-ng (2.0.11) focal; urgency=medium
* Bugs:
* #2445: lmAuth param sent to protected application
* #2446: Incorrect MIME type on /psgi.js
* #2448: Adaptative Authentication rule triggered several times
* #2449: SAML SLO using Redirect/POST binding does not work with multiple SP
* New features:
* #1987: add grant_type=client_credentials in OIDC
* Improvements:
* #2397: OAuth2 handler should make client_id and scopes of the access token available to rules and headers
* #2436: CheckUser displays headers as they have been defined in conf intead of how they are sent
* #2444: set oidcServiceKeyIdSig by default
-- Clément <clem.oudot@gmail.com> Sat, 30 Jan 2021 18:33:37 +0100
lemonldap-ng (2.0.10) stable; urgency=medium
* Bugs:
* #1978: can't configure variables to post in virtual host's form replay with lemonldap-cli
* #2245: Manager API does not call reloadUrls
* #2262: SAML: SP-initiated logout does not propagate to external authentication modules
* #2267: LDAP timeout does not apply to search/bind/etc
* #2293: LL:NG 2.0.8 Manager test for external/working SMTP fails @ SSL handshake, terminates connections
* #2304: Error when using SMTP over SSL in CentOS 7
* #2310: Misspelled parameter in call to ldap->search()
* #2315: CheckUser plugin: option rules rely on checked user rather than connected user
* #2318: Manager API: translate JSON booleans to int
* #2332: [security:low] removal of registrable 2F does not test the current authn level
* #2340: lemonldap-ng-cli restore does not work if the config backend is empty
* #2342: Calling logout page for unauthenticated user forces login
* #2344: Enable keepalive on LDAP connections
* #2347: [Manager API] postLogoutRedirectUris should be an array
* #2348: [Manager API] Bad URL in documentation
* #2352: skipRenewConfirmation and skipUpgradeConfirmation options do not work
* #2354: Lemonldap::NG::Common::Conf::msg is never reset and grows indefinitely
* #2355: Password policy checker broken in password reset by mail template
* #2357: CDA query parameter not parsed when query params are reordered
* #2361: Cannot remove OIDC consent from session explorer
* #2364: llngconnexion cookie in the StayConnected-Plugin rejected
* #2365: Check my last logins option does not work with StayConnected plugin
* #2366: StayConnected plugin does not work with 2FA
* #2367: skip rule doesn't work with DevOps handler
* #2369: Memory leak in Issuer::_redirect
* #2373: Remove spaces from generated login when user register account
* #2374: Missing form-check-input class in form groups
* #2375: Refresh session plugin: refresh result is not checked before returning JSON answer
* #2377: Reset expired password process does not work without _whatToTrace macro or if old password is not required
* #2378: Error in inGroup expansion
* #2383: Vhost with wildcard with % sign, configuration not loaded in manager
* #2387: logout does not clear handler cache
* #2399: Local password policy check should be disabled when clicking on "generate password" checkbox
* #2401: Selinux policy blocks cache after restorecon
* #2403: Missing Ldap attribute in CAS ticket if equals 0
* #2410: LDAP connectivity issues on startup cause fatal initialization error when passwordDB=LDAP
* #2411: Javascript error when local password policy configured and password tab disabled in menu
* #2413: checkstate returns error 500 with user parameter
* #2417: Error in cookie name used by lemonldap regexp
* #2420: Auth::SAML should handle missing NameID
* #2425: "Configuration error: xxx SAML metadata has no EntityID" when updating SAML sp in manager API
* #2426: twitter auth fails when coming from oidc/saml/cas service
* #2429: SAML sessions fill up with logout sessions that do not expire
* #2430: Password not updated in session after password change
* #2440: OIDC api: redirect URI not handled at top level during get/update operations
* New features:
* #2336: Adaptative Authentication Plugin
* #2391: Add extended function to test for registered second factor
* #2408: Add Chinese (Taiwan) translation
* Improvements:
* #714: Make password change compatible with Combination
* #716: Make password reset work with Combination
* #2232: lmAttrOrMacro test in Manager is too restrictive
* #2266: local password policy conflicts with LDAP password policy
* #2301: password reset page(s) CSS issues
* #2309: Unintialized $app in CAS Issuer during test
* #2314: CheckUser plugin: Append an option to display computed sessions data
* #2316: "New keys" in saml security configuration should generate a certificate
* #2317: Combination and fail2ban logs
* #2319: Allow the SAML signature alg to be set per-provider
* #2321: Can't save configuration with 2 CAS applications sharing the same hostname
* #2322: Support for SHA384 and SHA512 saml signatures
* #2329: Display a warning if password module is enabled without password backend
* #2330: Allow to configure OIDC claims type
* #2331: Warning in default Nginx configuration
* #2334: GlobalLogout plugin can sometimes found some non-SSO or corrupted sessions
* #2335: apache handler: allow users to override the port/scheme for redirections
* #2339: Plugins refactoring
* #2341: Make SHA256 the default signature method for SAML
* #2345: RGAA recommand alt tags to be empty for decoration images
* #2350: [security:low] Hiding session ids from the manager
* #2356: RGAA 5.4 requires arrays to have defined captions
* #2359: plugin engine for issuers
* #2360: Avoid assignment in expressions
* #2368: StayConnected-Plugin: when user-agent changes login is only possible after deleting cookies
* #2372: Add a domain whitelist to Auth::Kerberos
* #2380: CORS headers not sent by sendError
* #2381: Append a hook to be able to overwrite access log
* #2386: CheckUser does not resolve vhost aliases
* #2388: Allow custom SSL logos when using choice
* #2393: All messages printed in userLogger should use whatToTrace value to log user name
* #2398: CheckUser: Append an option to hide specific headers value depending on tested VHost
* #2404: Force deletion of corrupted sessions in DBI and LDAP backends
* #2406: Possibility to use a different mail for 2FA and password reset
* #2409: Update Spanish translation
* #2414: Manager evaluates macros with Safe Jail whereas useSafeJail has been disabled
* #2422: Missing alt attributes in mail HTML templates
* #2427: Make AssertionConsumerServiceURL available to SAML rules
* #2438: Add a confirmation when deleting second factor
* Templates:
* #2301: password reset page(s) CSS issues
* #2355: Password policy checker broken in password reset by mail template
* #2356: RGAA 5.4 requires arrays to have defined captions
* #2365: Check my last logins option does not work with StayConnected plugin
* #2366: StayConnected plugin does not work with 2FA
* #2374: Missing form-check-input class in form groups
* #2422: Missing alt attributes in mail HTML templates
* #2438: Add a confirmation when deleting second factor
* WebServer Confs:
* #2331: Warning in default Nginx configuration
* #2434: [security:medium] Headers are not deleted for unprotected or skip locations with nginx handler
-- Clément <clem.oudot@gmail.com> Sun, 17 Jan 2021 16:52:38 +0100
lemonldap-ng (2.0.9) stable; urgency=medium
* Bugs:

14
debian/changelog vendored
View File

@ -1,3 +1,17 @@
lemonldap-ng (2.0.11-1) unstable; urgency=medium
* New release. See changes on our website:
https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng
-- Clement OUDOT <clement@oodo.net> Sat, 30 Jan 2021 22:00:00 +0100
lemonldap-ng (2.0.10-1) unstable; urgency=medium
* New release. See changes on our website:
https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng
-- Clement OUDOT <clement@oodo.net> Sun, 17 Jan 2021 22:00:00 +0100
lemonldap-ng (2.0.9-1) unstable; urgency=medium
* New release. See changes on our website:

27
debian/control vendored
View File

@ -5,7 +5,8 @@ Section: perl
Priority: optional
Build-Depends: debhelper (>= 10),
po-debconf
Build-Depends-Indep: libapache-session-perl <!nocheck>,
Build-Depends-Indep: gsfonts <!nocheck>,
libapache-session-perl <!nocheck>,
libauth-yubikey-webclient-perl <!nocheck>,
libauthen-oath-perl <!nocheck>,
libcache-cache-perl <!nocheck>,
@ -30,6 +31,7 @@ Build-Depends-Indep: libapache-session-perl <!nocheck>,
libio-string-perl <!nocheck>,
libipc-run-perl <!nocheck>,
libjson-perl <!nocheck>,
libjson-xs-perl <!nocheck>,
liblasso-perl <!nocheck>,
libmime-tools-perl <!nocheck>,
libmouse-perl <!nocheck>,
@ -52,10 +54,12 @@ Build-Depends-Indep: libapache-session-perl <!nocheck>,
libwww-perl <!nocheck>,
libxml-libxml-perl <!nocheck>,
libxml-libxslt-perl <!nocheck>,
libxml-simple-perl <!nocheck>,
libtest-leaktrace-perl <!nocheck>,
python3-sphinx,
python3-sphinx-bootstrap-theme,
perl
Standards-Version: 4.5.0
Standards-Version: 4.5.1
Vcs-Browser: https://salsa.debian.org/perl-team/modules/packages/lemonldap-ng
Vcs-Git: https://salsa.debian.org/perl-team/modules/packages/lemonldap-ng.git
Homepage: https://lemonldap-ng.org/
@ -134,10 +138,10 @@ Architecture: all
Section: web
Depends: ${misc:Depends},
${perl:Depends},
liblemonldap-ng-handler-perl (= ${binary:Version}),
uwsgi-plugin-psgi
liblemonldap-ng-handler-perl (= ${binary:Version})
Recommends: libhttp-parser-xs-perl,
nginx-extras | nginx
uwsgi-plugin-psgi
Suggests: nginx-extras | nginx
Description: Lemonldap::NG uWSGI server
Lemonldap::NG is a complete Web-SSO system that can run with reverse-proxies
or directly on application webservers. It can be used in conjunction with
@ -160,8 +164,8 @@ Recommends: lemonldap-ng-fastcgi-server (= ${binary:Version}) | lemonldap-ng-uws
Suggests: libcache-memcached-perl,
libdigest-hmac-perl,
libsoap-lite-perl
Breaks: liblemonldap-ng-handler-perl (<< 1.9.1-2~)
Replaces: liblemonldap-ng-handler-perl (<< 1.9.1-2~)
Breaks: liblemonldap-ng-handler-perl (<< 1.9.1-2~), lemonldap-ng-fastcgi-server (<< 2.0.5~)
Replaces: liblemonldap-ng-handler-perl (<< 1.9.1-2~), lemonldap-ng-fastcgi-server (<< 2.0.5~)
Description: Lemonldap::NG handler part
Lemonldap::NG is a complete Web-SSO system that can run with reverse-proxies
or directly on application webservers. It can be used in conjunction with
@ -208,6 +212,7 @@ Depends: ${misc:Depends},
libcrypt-rijndael-perl,
libhtml-template-perl,
libjson-perl,
libjson-xs-perl,
libmouse-perl,
libplack-perl,
liburi-perl,
@ -217,7 +222,6 @@ Recommends: libapache-session-browseable-perl,
libcookie-baker-xs-perl,
libdbi-perl,
libhttp-parser-xs-perl,
libjson-xs-perl,
liblwp-protocol-https-perl,
libstring-random-perl
Suggests: libconvert-base32-perl,
@ -278,7 +282,8 @@ Depends: ${misc:Depends},
libtext-unidecode-perl,
libregexp-assemble-perl,
libemail-date-format-perl
Recommends: libcrypt-openssl-bignum-perl,
Recommends: gsfonts,
libcrypt-openssl-bignum-perl,
libconvert-base32-perl,
libio-string-perl,
libipc-run-perl,
@ -315,3 +320,7 @@ Description: Lemonldap::NG authentication portal part
the requested URL and the rule calculates if the user is authorized.
.
Lemonldap::NG::Portal provides the authentication portal.
.
You may have to install some suggested packages depending on plugins you
enabled. For example, libgd-securityimage-perl and gsfonts are needed if you
want to use Captcha, libcrypt-u2f-server-perl for U2F features,...

11
debian/tests/control vendored
View File

@ -1,32 +1,40 @@
# debian/tests/runner launch pkg-perl-autopkgtest tests for each library
Test-Command: ./debian/tests/runner build-deps lemonldap-ng-common
Depends: liblemonldap-ng-common-perl, @builddeps@, pkg-perl-autopkgtest
Features: test-name=common-test
Test-Command: ./debian/tests/runner build-deps lemonldap-ng-handler
Depends: liblemonldap-ng-handler-perl, @builddeps@, pkg-perl-autopkgtest
Features: test-name=handler-test
Test-Command: ./debian/tests/runner build-deps lemonldap-ng-portal
Depends: liblemonldap-ng-portal-perl, @builddeps@, pkg-perl-autopkgtest
Features: test-name=portal-test
Test-Command: ./debian/tests/runner build-deps lemonldap-ng-manager
Depends: liblemonldap-ng-manager-perl, @builddeps@, pkg-perl-autopkgtest
Features: test-name=manager-test
Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-common
Depends: liblemonldap-ng-common-perl, pkg-perl-autopkgtest, libmouse-perl
Restrictions: superficial, skippable
Features: test-name=runtime-deps-common
# Disable this one: skipped
#Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-handler
#Depends: liblemonldap-ng-handler-perl, pkg-perl-autopkgtest, libmouse-perl
#Restrictions: superficial, skippable
#Features: test-name=runtime-deps-handler
Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-portal
Depends: liblemonldap-ng-portal-perl, pkg-perl-autopkgtest, libmouse-perl
Restrictions: superficial, skippable
Features: test-name=runtime-deps-portal
Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-manager
Depends: liblemonldap-ng-manager-perl, pkg-perl-autopkgtest, libmouse-perl
Restrictions: superficial, skippable
Features: test-name=runtime-deps-manager
# Use pkg-perl-autopkgtest test for runtime-deps-and-recommends
# Some portal suggested dependencies are added here
@ -35,7 +43,10 @@ Depends: @, @builddeps@, pkg-perl-autopkgtest
, libyaml-perl, liblog-log4perl-perl
, libauthen-pam-perl, libauthen-radius-perl
, libweb-id-perl, libio-socket-timeout-perl
, libdatetime-format-rfc3339-perl
Restrictions: superficial
Features: test-name=runtime-deps-and-recommends
#Test-Command: ./debian/tests/runner heavy-deps
#Depends: @, pkg-perl-autopkgtest, pkg-perl-autopkgtest-heavy, libmouse-perl
#Features: test-name=heavy-deps

View File

@ -890,6 +890,17 @@
"allowOffline" : {
"type" : "boolean"
},
"accessTokenSignAlg" : {
"type" : "string",
"default" : "HS512",
"enum" : [ "none", "RS256", "RS384", "RS512" ]
},
"accessTokenJWT" : {
"type" : "bool"
},
"accessTokenClaims" : {
"type" : "bool"
},
"authnLevel" : {
"type" : "integer"
},
@ -908,7 +919,10 @@
"type" : "boolean"
},
"postLogoutRedirectUris" : {
"type" : "string"
"type" : "array",
"items" : {
"type" : "string"
}
},
"logoutType" : {
"type" : "string",
@ -921,6 +935,12 @@
"IDTokenForceClaims" : {
"type" : "boolean"
},
"additionalAudiences" : {
"type" : "array",
"items" : {
"type" : "string"
}
},
"requirePKCE" : {
"type" : "boolean"
},
@ -996,6 +1016,12 @@
},
"options" : {
"$ref" : "#/components/schemas/OidcOptions"
},
"scopeRules" : {
"type" : "object",
"example" : {
"write" : "requested and inGroup('writers')"
}
}
}
};
@ -1028,6 +1054,12 @@
},
"options" : {
"$ref" : "#/components/schemas/OidcOptions"
},
"scopeRules" : {
"type" : "object",
"example" : {
"write" : "requested and inGroup('writers')"
}
}
}
};
@ -1059,6 +1091,12 @@
},
"options" : {
"$ref" : "#/components/schemas/OidcOptions"
},
"scopeRules" : {
"type" : "object",
"example" : {
"write" : "requested and inGroup('writers')"
}
}
}
};
@ -1472,7 +1510,7 @@
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-addcasapp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X POST "/api/v1/api/v1/providers/cas/app"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X POST "https://manager-api.example.com/api/v1/providers/cas/app"</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-addcasapp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -1828,7 +1866,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-deleteCasApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/providers/cas/app/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/providers/cas/app/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-deleteCasApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -2169,7 +2207,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-findCasAppByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/cas/app/findByConfKey?pattern="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/cas/app/findByConfKey?pattern="</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-findCasAppByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -2515,7 +2553,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-findCasAppByServiceUrl-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/cas/app/findByServiceUrl?serviceUrl="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/cas/app/findByServiceUrl?serviceUrl="</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-findCasAppByServiceUrl-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -2905,7 +2943,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-getCasAppByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/cas/app/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/cas/app/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-getCasAppByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -3295,7 +3333,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-replaceCasApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "/api/v1/api/v1/providers/cas/app/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "https://manager-api.example.com/api/v1/providers/cas/app/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-replaceCasApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -3736,7 +3774,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Casapp-updateCasApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "/api/v1/api/v1/providers/cas/app/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "https://manager-api.example.com/api/v1/providers/cas/app/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Casapp-updateCasApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -4180,7 +4218,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Class2fa-deleteSecondFactors-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/secondFactor/{uid}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/secondFactor/{uid}"</code></pre>
</div>
<div class="tab-pane" id="examples-Class2fa-deleteSecondFactors-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -4470,7 +4508,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Class2fa-deleteSecondFactorsById-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/secondFactor/{uid}/id/{id}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/secondFactor/{uid}/id/{id}"</code></pre>
</div>
<div class="tab-pane" id="examples-Class2fa-deleteSecondFactorsById-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -4788,7 +4826,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Class2fa-deleteSecondFactorsByType-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/secondFactor/{uid}/type/{type}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/secondFactor/{uid}/type/{type}"</code></pre>
</div>
<div class="tab-pane" id="examples-Class2fa-deleteSecondFactorsByType-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -5106,7 +5144,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Class2fa-getSecondFactors-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/secondFactor/{uid}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/secondFactor/{uid}"</code></pre>
</div>
<div class="tab-pane" id="examples-Class2fa-getSecondFactors-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -5445,7 +5483,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Class2fa-getSecondFactorsById-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/secondFactor/{uid}/id/{id}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/secondFactor/{uid}/id/{id}"</code></pre>
</div>
<div class="tab-pane" id="examples-Class2fa-getSecondFactorsById-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -5812,7 +5850,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Class2fa-getSecondFactorsByType-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/secondFactor/{uid}/type/{type}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/secondFactor/{uid}/type/{type}"</code></pre>
</div>
<div class="tab-pane" id="examples-Class2fa-getSecondFactorsByType-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -6182,7 +6220,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Default-status-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/status"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/status"</code></pre>
</div>
<div class="tab-pane" id="examples-Default-status-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -6489,7 +6527,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-addMenuApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X POST "/api/v1/api/v1/menu/app/{cat}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X POST "https://manager-api.example.com/api/v1/menu/app/{cat}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-addMenuApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -6931,7 +6969,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-deleteMenuApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/menu/app/{cat}/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/menu/app/{cat}/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-deleteMenuApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -7303,7 +7341,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-findMenuAppByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/menu/app/{cat}/findByConfKey?pattern="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/menu/app/{cat}/findByConfKey?pattern="</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-findMenuAppByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -7687,7 +7725,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-getMenuAppByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/menu/app/{cat}/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/menu/app/{cat}/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-getMenuAppByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -8108,7 +8146,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-getMenuApps-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/menu/app/{cat}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/menu/app/{cat}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-getMenuApps-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -8502,7 +8540,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-replaceMenuApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "/api/v1/api/v1/menu/app/{cat}/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "https://manager-api.example.com/api/v1/menu/app/{cat}/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-replaceMenuApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -8974,7 +9012,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menuapp-updateMenuApp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "/api/v1/api/v1/menu/app/{cat}/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "https://manager-api.example.com/api/v1/menu/app/{cat}/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menuapp-updateMenuApp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -9449,7 +9487,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menucat-addMenuCat-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X POST "/api/v1/api/v1/menu/cat"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X POST "https://manager-api.example.com/api/v1/menu/cat"</code></pre>
</div>
<div class="tab-pane" id="examples-Menucat-addMenuCat-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -9805,7 +9843,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menucat-deleteMenuCat-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/menu/cat/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/menu/cat/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menucat-deleteMenuCat-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -10146,7 +10184,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menucat-findMenuCatByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/menu/cat/findByConfKey?pattern="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/menu/cat/findByConfKey?pattern="</code></pre>
</div>
<div class="tab-pane" id="examples-Menucat-findMenuCatByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -10492,7 +10530,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menucat-getMenuCatByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/menu/cat/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/menu/cat/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menucat-getMenuCatByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -10882,7 +10920,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menucat-replaceMenuCat-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "/api/v1/api/v1/menu/cat/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "https://manager-api.example.com/api/v1/menu/cat/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menucat-replaceMenuCat-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -11323,7 +11361,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Menucat-updateMenuCat-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "/api/v1/api/v1/menu/cat/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "https://manager-api.example.com/api/v1/menu/cat/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Menucat-updateMenuCat-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -11767,7 +11805,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-addoidcrp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X POST "/api/v1/api/v1/providers/oidc/rp"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X POST "https://manager-api.example.com/api/v1/providers/oidc/rp"</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-addoidcrp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -12123,7 +12161,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-deleteOidcRp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/providers/oidc/rp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/providers/oidc/rp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-deleteOidcRp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -12464,7 +12502,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-findOidcRpByClientId-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/oidc/rp/findByClientId?clientId="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/oidc/rp/findByClientId?clientId="</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-findOidcRpByClientId-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -12854,7 +12892,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-findOidcRpByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/oidc/rp/findByConfKey?pattern="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/oidc/rp/findByConfKey?pattern="</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-findOidcRpByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -13200,7 +13238,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-getOidcRpByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/oidc/rp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/oidc/rp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-getOidcRpByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -13590,7 +13628,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-replaceOidcRp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "/api/v1/api/v1/providers/oidc/rp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "https://manager-api.example.com/api/v1/providers/oidc/rp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-replaceOidcRp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -14031,7 +14069,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Oidcrp-updateOidcRp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "/api/v1/api/v1/providers/oidc/rp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "https://manager-api.example.com/api/v1/providers/oidc/rp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Oidcrp-updateOidcRp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -14475,7 +14513,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-addsamlsp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X POST "/api/v1/api/v1/providers/saml/sp"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X POST "https://manager-api.example.com/api/v1/providers/saml/sp"</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-addsamlsp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -14831,7 +14869,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-deleteSamlSp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "/api/v1/api/v1/providers/saml/sp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X DELETE "https://manager-api.example.com/api/v1/providers/saml/sp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-deleteSamlSp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -15172,7 +15210,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-findSamlSpByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/saml/sp/findByConfKey?pattern="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/saml/sp/findByConfKey?pattern="</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-findSamlSpByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -15518,7 +15556,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-findSamlSpByEntityId-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/saml/sp/findByEntityId?entityId="</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/saml/sp/findByEntityId?entityId="</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-findSamlSpByEntityId-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -15908,7 +15946,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-getSamlSpByConfKey-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X GET "/api/v1/api/v1/providers/saml/sp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X GET "https://manager-api.example.com/api/v1/providers/saml/sp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-getSamlSpByConfKey-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -16298,7 +16336,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-replaceSamlSp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "/api/v1/api/v1/providers/saml/sp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PUT "https://manager-api.example.com/api/v1/providers/saml/sp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-replaceSamlSp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;
@ -16739,7 +16777,7 @@ except ApiException as e:
<div class="tab-content">
<div class="tab-pane active" id="examples-Samlsp-updateSamlSp-0-curl">
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "/api/v1/api/v1/providers/saml/sp/{confKey}"</code></pre>
<pre class="prettyprint"><code class="language-bsh">curl -X PATCH "https://manager-api.example.com/api/v1/providers/saml/sp/{confKey}"</code></pre>
</div>
<div class="tab-pane" id="examples-Samlsp-updateSamlSp-0-java">
<pre class="prettyprint"><code class="language-java">import io.swagger.client.*;

View File

@ -9,6 +9,7 @@ Applications
applications/aws
applications/awx
applications/bugzilla
applications/bigbluebutton
applications/cornerstone
applications/discourse
applications/django
@ -83,6 +84,7 @@ Application Configuration
.. image:: applications/alfresco_logo.png :doc:`Alfresco<applications/alfresco>` ✔ ✔
.. image:: applications/logo_amazon_web_services.jpg :doc:`Amazon Web Services<applications/aws>`
.. image:: applications/logo-awx.png :doc:`AWX (Ansible Tower)<applications/awx>`
.. image:: applications/bigbluebutton-logo.png :doc:`BigBlueButton<applications/bigbluebutton>`
.. image:: applications/bugzilla_logo.png :doc:`Bugzilla<applications/bugzilla>`
.. image:: applications/csod_logo.png :doc:`Cornerstone<applications/cornerstone>`
.. image:: applications/discourse.jpg :doc:`Discourse<applications/discourse>` ✔ ✔

View File

@ -163,6 +163,16 @@ This is the configuration of the IdP :
inside AWX
- "url": "https://auth.example.com/saml/singleSignOn" SAML SSO Url
SAML Security Config
^^^^^^^^^^^^^^^^^^^^
::
{
"requestedAuthnContext": false,
"authnRequestsSigned": true
}
Save your configuration.
LemonLDAP:NG

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,64 @@
BigBlueButton
=============
|logo|
Presentation
------------
`BigBlueButton <https://bigbluebutton.org/>`__ is a web conferencing system
designed for online learning. It offers audio/video sharing, presentations with
extended whiteboard capabilities - such as a pointer, zooming and drawing -
public and private chat, breakout rooms, screen sharing, integrated VoIP using
FreeSWITCH, and support for presentation of PDF documents and Microsoft Office
documents.
Its user-facing interface, *Greenlight*, can be configured to authenticate users with :doc:`OpenID Connect <../idpopenidconnect>` since version 2.7.17.
Configuration
--------------
LL:NG
~~~~~
Make sure you have already
:doc:`enabled OpenID Connect<../idpopenidconnect>` on your LemonLDAP::NG
server
Make sure you have generated a set of signing keys in
``OpenID Connect Service`` » ``Security`` » ``Keys``
You also need to set a Signing key ID to a non-empty value of your choice.
Then, add a Relaying Party with the following configuration
- Options » Authentification » Client ID : choose a client ID, such as ``my_client_id``
- Options » Authentification » Client Secret : choose a client secret, such as ``my_client_secret``
- Options » Allowed redirection address : ``https://my_greenlight_server/b/auth/openid_connect/callback``
- Options » ID Token Signature Algorithm : ``RS256``
- Adjust your Exported Attributes to send the correct session variables in the ``email`` and ``name`` claims.
Greenlight
~~~~~~~~~~
Configure the following environment variables in your greenlight `.env` file ::
OPENID_CONNECT_CLIENT_ID=my_client_id
OPENID_CONNECT_CLIENT_SECRET=my_client_secret
OPENID_CONNECT_ISSUER=https://auth.example.com
OPENID_CONNECT_UID_FIELD=sub
OAUTH2_REDIRECT=https://my_greenlight_server/b/
Notes
~~~~~
* Your ID Token Signature Algorithm has to be RSxxx, symmetric algorithms seem broken as of Greenlight 2.7.17
* ``OAUTH2_REDIRECT`` must match the URL you use to access Greenlight. the
``auth/openid_connect/callback`` suffix must be omitted
* Greenlight will not work if your LemonLDAP::NG server is not served over HTTPS using a publically recognized certificate authority (such as Let's Encrypt)
.. |logo| image:: /applications/bigbluebutton-logo.png
:class: align-center

View File

@ -16,12 +16,7 @@ Configuration
Gerrit
------
`Install <https://gerrit-review.googlesource.com/Documentation/config-plugins.html#installation>`__ the OAuth Provider plugin.
.. tip::
The LemonLDAP::NG support was added on February 23, 2020.
If you can't find a prebuilt package, you can use this `dockerfile <https://github.com/atisne/gerrit-oauth-build>`__ to build your own.
`Install <https://gerrit-review.googlesource.com/Documentation/config-plugins.html#installation>`__ the OAuth Provider plugin. A prebuilt package of the plugin can be found on the `Gerrit CI <https://gerrit-ci.gerritforge.com/job/plugin-oauth-bazel-master-master/lastSuccessfulBuild/artifact/bazel-bin/plugins/oauth/oauth.jar>`__.
Then, configure Gerrit:

View File

@ -101,15 +101,15 @@ with the following parameters:
* ``username``: set it to the session attribute containing the user login
* ``name``: session attribute containing the user's full name
* ``email``: session attribute containing the user's email
* ``id``: session attribute containing the user's numeric ID
* ``id``: session attribute containing the user's numeric ID. You must set
this claim type to *Integer*
.. danger::
Mattermost absolutely needs to receive a numerical value
in the ``id`` claim. If you are using a LDAP server, you could use the
``uidNumber`` LDAP attribute. If you use something else, you will have
to find a trick to assign a unique numeric ID to each Mattermost user.
Mattermost absolutely needs to receive a numerical value in the ``id``
claim. If you are using a LDAP server, you could use the ``uidNumber`` LDAP
attribute. If you use something else, you will have to find a way to
assign a unique numeric ID to each Mattermost user.
The ``id`` attribute has to be different for each user, since this is
the field Mattermost will use internally to map Gitlab identities to
@ -123,10 +123,10 @@ in ``(*GitLabUser).IsValid(...)`` , it probably means that you are not
exporting the correct attributes, but it can also mean that ``id`` is
exported as a JSON string.
If this case, it can help to create a macro, for example
``uidNumber_n``, with a value of ``$uidNumber + 0`` to force conversion
to a numeric value. You must then export it as the ``id`` field in the
Relaying Party configuration.
.. note::
An issue in version 2.0.9 prevented the ``id`` field from being sent correctly.
Upgrade your LemonLDAP-NG installation to at least 2.0.10 and :ref:`set the claim
type <oidcexportedattr>` to *Integer*
.. |image0| image:: /applications/mattermost_logo.png
:class: align-center

View File

@ -30,14 +30,13 @@ software <https://docs.nextcloud.com/server/10/admin_manual/installation/index.h
If your NextCloud is behind a proxy (thus having a private
IP), metadata generated by NextCloud won't work.
Consider changing the configuration of NextCloud to force the domain, in
Consider changing the configuration of NextCloud to force the domain and the protocol, in
**$nextcloudrootwww/config/config.php**, add the following:
.. code:: php
'overwritehost' => 'nextcloud.example.com',
'overwriteprotocol' => 'https',
You also need to enable the "SAML authentication" plugin in your
NextCloud. <code> + Apps -> Not enabled -> SAML authentication</code>

View File

@ -49,9 +49,11 @@ Then, go in ``Choice Parameters``:
- **URL parameter**: parameter name used to set choice value (default:
``lmAuth``)
- **AuthBasic handler parameter**: authentication module used by
AuthBasic handler
- **Allowed modules**: click on ``New chain`` to add a choice.
- **AuthBasic handler parameter**: authentication module called by
AuthBasic handler (:doc:`AuthBasic handler<handlerauthbasic>`)
- **FindUser plugin parameter**: authentication module called by
Find user plugin (:doc:`Find user plugin<finduser>`)
|image0|
@ -75,6 +77,12 @@ Define here:
$env->{urldc} =~ /test1\.example\.com/
.. note::
Federated authentication need pdata cookie.
SameSite cookie value must be set to "Lax" or "None".
See :doc:`SSO cookie parameters<ssocookie>`
.. note::
Authentication request to an another URL than Portal URL can lead
@ -100,7 +108,7 @@ Define here:
.. tip::
You can also override some LLNG parameters for each chain. See
:doc:`Parameter list<parameterlist>` to have the key names to use
:doc:`Parameters list<parameterlist>` to have the key names to use
.. |image0| image:: /documentation/manager-choice.png
:class: align-center

View File

@ -1,11 +1,11 @@
Combination of authentication schemes
=====================================
============== ===== ========
============== ===== ==================
Authentication Users Password
============== ===== ========
✔ ✔
============== ===== ========
============== ===== ==================
✔ ✔ ✔ (since *2.0.10*)
============== ===== ==================
Presentation
------------
@ -184,6 +184,47 @@ lemonldap-ng.ini. Example:
[portal]
combinationForms = standardform, openidform
Password management
-------------------
.. versionadded:: 2.0.10
Not all configurations of the Combination module allow password management.
If your combination looks like this ::
[Kerberos, LDAP] or [LDAP]
Then you can simply set ``LDAP`` as the password module, and password changes
and reset will work as expected.
If your combination looks like this ::
[LDAP1] or [LDAP2]
Then you can configure the ``Combination`` password module to automatically
send password changes to the LDAP server which was used during authentication.
This module also enables password reset.
.. note::
You can set the ``_cmbPasswordDB`` session variable to manually select which
backend will be called when changing the password. This is useful when using
SASL delegation
Limitations
~~~~~~~~~~~
* When using password reset with a combination of 2 or more LDAP servers, you
need to make sure that there is no duplication of email addresses between all
your servers. If an email exists in more than one server, the password will
be reset on the first LDAP server that contains this email address
* Combinations using the ``and`` boolean expression will not cause passwords to
be changed in both backends for now
* Forcing the user to reset their password on next login is not currently
supported by the combination module
Known problems
--------------

View File

@ -205,7 +205,11 @@ Password
reset (default: TRUE).
- **Allow a user to reset his expired password**: if activated, the
user will be prompted to change password if his password is expired
(default: 0)
(default: disabled)
- **Search for user before password change**: this option forces the password
change module to search for the user again, refreshing its DN. This feature
is only useful in rare cases when you use LDAP as the password module, but
not as the UserDB module. (default: enabled)
- **IBM Tivoli DS support**: enable this option if you use ITDS. LL::NG
will then scan error message to return a more precise error to the
user.

View File

@ -56,7 +56,7 @@ Google France Connect
.. attention::
OpenID-Connect specification isn't finished for logout
OpenID-Connect specification is not finished for logout
propagation. So logout initiated by relaying-party will be forward to
OpenID-Connect provider but logout initiated by the provider (or another
RP) will not be propagated. LLNG will implement this when spec will be
@ -127,7 +127,9 @@ parameter, for example:
.. attention::
If you use the :doc:`choice backend<authchoice>`, you
need to add the choice parameter in redirect URL
need to add the choice parameter in redirect URL or
set SameSite cookie value to "Lax" or "None".
See :doc:`SSO cookie parameters<ssocookie>`
After registration, the OP must give you a client ID and a client
secret, that will be used to configure the OP in LL::NG.
@ -148,6 +150,8 @@ The OP should publish its metadata in a JSON file (see for example
`Google
metadata <https://accounts.google.com/.well-known/openid-configuration>`__).
Copy the content of this file in the textarea.
Portal discovery document can be found here:
https://#portal#/.well-known/openid-configuration
If no metadata is available, you need to write them in the textarea.
Mandatory fields are:
@ -217,7 +221,7 @@ Options
- **Client ID**: Client ID given by OP
- **Client secret**: Client secret given by OP
- **Store ID token**: Allows one to store the ID token (JWT) inside
user session. Don't enable it unless you need to replay this token
user session. Do not enable it unless you need to replay this token
on an application, or if you need the id_token_hint parameter when
using logout.

View File

@ -0,0 +1,35 @@
Browseable LDAP session backend
===============================
LemonLDAP::NG configuration
---------------------------
Go in the Manager and set the session module to ``Apache::Session::Browseable::LDAP`` for each session type you intend to use:
* ``General parameters`` » ``Sessions`` » ``Session storage`` » ``Apache::Session module``
* ``General parameters`` » ``Sessions`` » ``Persistent sessions`` » ``Apache::Session module``
* ``CAS Service`` » ``CAS sessions module name``
* ``OpenID Connect Service`` » ``Sessions`` » ``Sessions module name``
* ``SAML2 Service`` » ``Advanced`` » ``SAML sessions module name``
The fill out the corresponding module parameters:
======================== ================================= ===============================
Required parameters
======================== ================================= ===============================
Name Comment Example
**ldapServer** URI of the server ldap://localhost
**ldapConfBase** DN of sessions branch ou=sessions,dc=example,dc=com
**ldapBindDN** Connection login cn=admin,dc=example,dc=password
**ldapBindPassword** Connection password secret
**Index** Fields to index refer to :ref:`fieldstoindex`
Optional parameters
Name Comment Default value
**ldapObjectClass** Objectclass of the entry applicationProcess
**ldapAttributeId** Attribute storing session ID cn
**ldapAttributeContent** Attribute storing session content description
**ldapAttributeIndex** Attribute storing index ou
**ldapVerify** Perform certificate validation require (use none to disable)
**ldapCAFile** Path of CA file bundle (system CA bundle)
**ldapCAPath** Perform CA directory (system CA bundle)
======================== ================================= ===============================

View File

@ -0,0 +1,120 @@
Browseable MySQL session backend
================================
Prerequisites
-------------
First, make sure you have installed the ``DBD::mysql`` perl module.
On Debian-based distributions ::
apt install libdbd-mysql-perl
On Fedora-based distributions ::
yum install 'perl(DBD::mysql)'
Create database schema
----------------------
Create the following tables. You may skip the session types you are not going to use, but you need at least ``sessions`` and ``psessions``
::
CREATE TABLE sessions (
id varchar(64) not null primary key,
a_session text,
_whatToTrace varchar(64),
_session_kind varchar(15),
ipAddr varchar(64),
_utime bigint,
_httpSessionType varchar(64),
user varchar(64)
) DEFAULT CHARSET utf8;
CREATE INDEX i_s__whatToTrace ON sessions (_whatToTrace);
CREATE INDEX i_s__session_kind ON sessions (_session_kind);
CREATE INDEX i_s__utime ON sessions (_utime);
CREATE INDEX i_s_ipAddr ON sessions (ipAddr);
CREATE INDEX i_s__httpSessionType ON sessions (_httpSessionType);
CREATE INDEX i_s_user ON sessions (user);
CREATE TABLE psessions (
id varchar(64) not null primary key,
a_session text,
_session_kind varchar(15),
_httpSessionType varchar(64),
_whatToTrace varchar(64),
ipAddr varchar(64),
_session_uid varchar(64)
) DEFAULT CHARSET utf8;
CREATE INDEX i_p__session_kind ON psessions (_session_kind);
CREATE INDEX i_p__httpSessionType ON psessions (_httpSessionType);
CREATE INDEX i_p__session_uid ON psessions (_session_uid);
CREATE INDEX i_p_ipAddr ON psessions (ipAddr);
CREATE INDEX i_p__whatToTrace ON psessions (_whatToTrace);
CREATE TABLE samlsessions (
id varchar(64) not null primary key,
a_session text,
_session_kind varchar(15),
_utime bigint,
ProxyID varchar(64),
_nameID varchar(128),
_assert_id varchar(64),
_art_id varchar(64),
_saml_id varchar(64)
) DEFAULT CHARSET utf8;
CREATE INDEX i_a__session_kind ON samlsessions (_session_kind);
CREATE INDEX i_a__utime ON samlsessions (_utime);
CREATE INDEX i_a_ProxyID ON samlsessions (ProxyID);
CREATE INDEX i_a__nameID ON samlsessions (_nameID);
CREATE INDEX i_a__assert_id ON samlsessions (_assert_id);
CREATE INDEX i_a__art_id ON samlsessions (_art_id);
CREATE INDEX i_a__saml_id ON samlsessions (_saml_id);
CREATE TABLE oidcsessions (
id varchar(64) not null primary key,
a_session text,
_session_kind varchar(15),
_utime bigint
) DEFAULT CHARSET utf8;
CREATE INDEX i_o__session_kind ON oidcsessions (_session_kind);
CREATE INDEX i_o__utime ON oidcsessions (_utime);
CREATE TABLE cassessions (
id varchar(64) not null primary key,
a_session text,
_session_kind varchar(15),
_utime bigint,
_cas_id varchar(128),
pgtIou varchar(128)
) DEFAULT CHARSET utf8
CREATE INDEX i_c__session_kind ON cassessions (_session_kind);
CREATE INDEX i_c__utime ON cassessions (_utime);
CREATE INDEX i_c__cas_id ON cassessions (_cas_id);
CREATE INDEX i_c_pgtIou ON cassessions (pgtIou);
LemonLDAP::NG configuration
---------------------------
Go in the Manager and set the session module to ``Apache::Session::Browseable::PgJSON`` for each session type you intend to use:
* ``General parameters`` » ``Sessions`` » ``Session storage`` » ``Apache::Session module``
* ``General parameters`` » ``Sessions`` » ``Persistent sessions`` » ``Apache::Session module``
* ``CAS Service`` » ``CAS sessions module name``
* ``OpenID Connect Service`` » ``Sessions`` » ``Sessions module name``
* ``SAML2 Service`` » ``Advanced`` » ``SAML sessions module name``
Then, set the following module options:
=================== ================================================= =============================================================
Required parameters
=================== ================================================= =============================================================
Name Comment Example
**DataSource** The `DBI <https://metacpan.org/pod/DBI>`__ string dbi:mysql:database=lemonldap-ng
**UserName** The database username lemonldapng
**Password** The database password mysuperpassword
**TableName** Table name (optional) sessions
**Index** Fields to index refer to :ref:`fieldstoindex`
=================== ================================================= =============================================================

View File

@ -7,250 +7,53 @@ Presentation
Browseable session backend
(`Apache::Session::Browseable <https://metacpan.org/pod/Apache::Session::Browseable>`__)
works exactly like Apache::Session::\* corresponding module but add
index that increase :ref:`session explorer<session-explorer>` and
:ref:`session restrictions<session-restrictions>` performances.
If you use features like SAML (authentication and issuer), CAS (issuer)
and password reset self-service, you also need to index some fields.
index that increase the speed of some operations. It is recommended in production deployments.
.. note::
Without index, LL::NG will have to retrieve all sessions stored in
backend and parse them to find the needed sessions. With index, LL::NG
wil be able to get only wanted sessions from the backend.
backend and deserialize then filter each of them.
The following table list fields to index depending on the feature you
want to increase performance:
The following table list fields to index for each session type:
====================================== ============= ===================================================================
Feature Session Type Fields to index
====================================== ============= ===================================================================
Database cleanup *(cron)* All \_session_kind \_utime
Session explorer Global \_session_kind ipAddr \_httpSessionType *WHATTOTRACE*
Session explorer Persistent \_session_kind \_session_uid ipAddr \_httpSessionType *WHATTOTRACE*
Session restrictions Global \_session_kind ipAddr *WHATTOTRACE*
Password reset by email Global user
SAML Session SAML \_saml_id ProxyID \_nameID \_assert_id \_art_id
====================================== ============= ===================================================================
.. _fieldstoindex:
List of fields to index by session type
---------------------------------------
========================== ======================================================================
Session Type Fields to index
========================== ======================================================================
Sessions (global) \_whatToTrace \_session_kind \_utime ipAddr \_httpSessionType user
Persistent sessions \_session\_kind \_httpSessionType \_session\_uid ipAddr \_whatToTrace
CAS sessions \_cas\_id pgtIou
SAML sessions \_session_kind \_utime \_saml_id ProxyID \_nameID \_assert_id \_art_id
OpenID Connect sessions \_session_kind \_utime
========================== ======================================================================
.. note::
If you have configured LemonLDAP::NG to use something other than
`_whatToTrace` as the main session identifier, you must replace
`_whatToTrace` with the new session field in the previous list
See Apache::Session::Browseable man page to see how use indexes.
.. attention::
\ *WHATTOTRACE* must be replaced by the attribute or
macro configured in the What To Trace parameter (REMOTE_USER). By
default: **\_whatToTrace**\
.. tip::
It is advised to use separate session backends for standard
sessions, SAML sessions and CAS sessions, in order to manage index
separately.
It is advised to use separate session backends for standard sessions, SAML
sessions and CAS sessions, in order to avoid unused indexes.
.. note::
Documentation below explains how set index on ipAddr and
\_whatToTrace. Adapt it to configure the index you need.
Available backends
------------------
Browseable NoSQL
----------------
You can use Redis and set up the database like explained in
:doc:`Redis session backend<nosqlsessionbackend>`.
You then just have to add the ``Index`` parameter in
``General parameters`` » ``Sessions`` » ``Session storage`` »
``Apache::Session module`` :
=================== ============ ====================
Required parameters
=================== ============ ====================
Name Comment Example
**server** Redis server 127.0.0.1:6379
**Index** Index \_whatToTrace ipAddr
=================== ============ ====================
Browseable SQL
--------------
.. note::
This documentation concerns PostgreSQL. Some adaptations are
needed with other databases. When using
Apache::Session::Browseable::Postgres, it
is strongly recommended to use version 1.3.1 at least. See `bug
1732 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1732>`__.
Prepare database
~~~~~~~~~~~~~~~~
Database must be prepared exactly like in
:ref:`SQL session backend<sqlsessionbackend-prepare-the-database>`
except that a field must be added for each data to index.
.. attention::
Data written to UNLOGGED tables is not written to the
WAL, which makes them considerably faster than ordinary tables. However,
they are not crash-safe: an unlogged table is automatically truncated
after a crash or unclean shutdown. The contents of an unlogged table are
also not replicated to standby servers. Any indexes created on an
unlogged table are automatically unlogged as well.
Apache::Session::Browseable::Postgres
example:
::
CREATE UNLOGGED TABLE sessions (
id varchar(64) not null primary key,
a_session text,
_whatToTrace text,
_session_kind text,
_utime bigint,
_httpSessionType text,
ipAddr text
);
CREATE INDEX uid1 ON sessions USING BTREE (_whatToTrace text_pattern_ops);
CREATE INDEX s1 ON sessions (_session_kind);
CREATE INDEX u1 ON sessions (_utime);
CREATE INDEX ip1 ON sessions USING BTREE (ipAddr);
CREATE INDEX h1 ON sessions (_httpSessionType);
.. attention::
For Session Explorer and one-off sessions, it is
recommended to use BTREE or any index method that indexes partial
content.
"id" fieds is set to ``varchar(64)`` (instead of char(32)) to use the
now recommended SHA256 hash algorithm. See
:doc:`Sessions<sessions>` for more details.
.. tip::
With new
Apache::Session::Browseable::PgHstore
and **PgJSON**, you don't need to declare indexes in ``CREATE TABLE``
since "json" and "hstore" type are browseable. You should anyway add
some indexes *(see manpage)*.
Manager
~~~~~~~
Go in the Manager and set the session module
(`Apache::Session::Browseable::MySQL <https://metacpan.org/pod/Apache::Session::Browseable::MySQL>`__
for MySQL) in ``General parameters`` » ``Sessions`` »
``Session storage`` » ``Apache::Session module`` and add the following
parameters (case sensitive):
=================== ================================================= =============================================================
Required parameters
=================== ================================================= =============================================================
Name Comment Example
**DataSource** The `DBI <https://metacpan.org/pod/DBI>`__ string dbi:Pg:database=lemonldap-ng
**UserName** The database username lemonldapng
**Password** The database password mysuperpassword
**Index** Index \_whatToTrace ipAddr \_session_kind \_utime \_httpSessionType
**TableName** Table name (optional) sessions
=================== ================================================= =============================================================
.. tip::
Apache::Session::Browseable::MySQL doesn't use locks so performances are
keeped.
For databases like PostgreSQL, don't forget to add "Commit" with a value
of 1
Browseable LDAP
---------------
Go in the Manager and set the session module to
``Apache::Session::Browseable::LDAP``. Then configure the options like
in :doc:`LDAP session backend<ldapsessionbackend>`.
You need to add the ``Index`` field and can also configure the
``ldapAttributeIndex`` field to set the attribute name where index
values will be stored.
======================== ================================= ===============================
Required parameters
======================== ================================= ===============================
Name Comment Example
**ldapServer** URI of the server ldap://localhost
**ldapConfBase** DN of sessions branch ou=sessions,dc=example,dc=com
**ldapBindDN** Connection login cn=admin,dc=example,dc=password
**ldapBindPassword** Connection password secret
**Index** Index list \_whatToTrace ipAddr
Optional parameters
Name Comment Default value
**ldapObjectClass** Objectclass of the entry applicationProcess
**ldapAttributeId** Attribute storing session ID cn
**ldapAttributeContent** Attribute storing session content description
**ldapAttributeIndex** Attribute storing index ou
**ldapVerify** Perform certificate validation require (use none to disable)
**ldapCAFile** Path of CA file bundle (system CA bundle)
**ldapCAPath** Perform CA directory (system CA bundle)
======================== ================================= ===============================
Security
--------
Restrict network access to the backend.
You can also use different user/password for your servers by overriding
parameters ``globalStorage`` and ``globalStorageOptions`` in
lemonldap-ng.ini file.
Performances
------------
Here are some recommended configurations:
**Browseable::Postgres**:
::
CREATE UNLOGGED TABLE sessions (
id varchar(64) not null primary key,
a_session text,
_whatToTrace text,
_session_kind text,
_utime bigint,
_httpSessionType text,
ipAddr text
);
CREATE INDEX uid1 ON sessions USING BTREE (_whatToTrace text_pattern_ops);
CREATE INDEX s1 ON sessions (_session_kind);
CREATE INDEX u1 ON sessions (_utime);
CREATE INDEX ip1 ON sessions USING BTREE (ipAddr);
CREATE INDEX h1 ON sessions (_httpSessionType);
**Browseable::MySQL**:
::
CREATE TABLE sessions (
id varchar(64) not null primary key,
a_session text,
_whatToTrace varchar(64),
_session_kind varchar(15),
user text,
_utime bigint,
ipAddr varchar(64)
);
CREATE INDEX uid1 ON sessions (_whatToTrace) USING BTREE;
CREATE INDEX _s1 ON sessions (_session_kind);
CREATE INDEX _u1 ON sessions (_utime);
CREATE INDEX ip1 ON sessions (ipAddr) USING BTREE;
.. toctree::
:maxdepth: 1
PgJSON Backend (recommended) <pgjsonsessionbackend>
browseablemysqlsessionbackend
browseableldapsessionbackend
nosqlsessionbackend

View File

@ -19,25 +19,25 @@ configuration file with the following content:
# This example migrates psessions from the default File backend to a PostgreSQL database
[sessions_from]
storageModule = Apache::Session::File
storageModuleOptions = { \\
'Directory' => '/var/lib/lemonldap-ng/psessions', \\
'LockDirectory' => '/var/lib/lemonldap-ng/psessions/lock', \\
storageModuleOptions = { \
'Directory' => '/var/lib/lemonldap-ng/psessions', \
'LockDirectory' => '/var/lib/lemonldap-ng/psessions/lock', \
}
# Only convert some session types
# sessionKind = Persistent, SSO
[sessions_to]
storageModule = Apache::Session::Browseable::Postgres
storageModuleOptions = { \\
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \\
'UserName' => 'lemonldaplogin', \\
'Password' => 'lemonldappw', \\
'Commit' => 1, \\
'Index' => 'ipAddr _whatToTrace user', \\
'TableName' => 'psessions', \\
storageModuleOptions = { \
'DataSource' => 'DBI:Pg:database=lemonldapdb;host=pg.example.com', \
'UserName' => 'lemonldaplogin', \
'Password' => 'lemonldappw', \
'Commit' => 1, \
'Index' => 'ipAddr _whatToTrace user', \
'TableName' => 'psessions', \
}
Invokation
Invocation
----------
``convertSessions -c job.ini``

View File

@ -0,0 +1,55 @@
Check DevOps plugin
===================
This plugin can be used to check the :doc:`DevOps<devopshandler>` file.
Configuration
-------------
Just enable it in the manager (section “plugins”).
- **Parameters**:
- **Activation**: Enable / Disable this plugin
- **Download file**: Allow users to download DevOps file from a remote server by
providing an URL (By example: http://myapp.example.com:8080). Plugin will
try to retrieve remote file by sending a request (i.e.
http://myapp.example.com:8080/rules.json)
Usage
-----
When enabled, ``/checkdevops`` URL path is handled by this plugin.
Then, you can paste a file to test your rules and headers.
Example
~~~~~~~
DevOps handler requires a rules.json file to define
access rules and headers:
.. code-block:: json
{
"rules": {
"^/admin": "$uid eq 'admin'",
"default": "accept"
},
"headers": {
"Auth-User": "$uid"
}
}
.. note::
This plugin displays ALL user session attributes except
the hidden ones.
You have to restrict access to specific users like DevOps teams
by setting an access rule like other VirtualHosts.
By example: ``$groups =~ /\bdevops\b/``
.. attention::
Be careful to not display secret attributes.
checkDevOps plugin uses hidden attributes option.

View File

@ -22,17 +22,19 @@ Just enable it in the manager (section “plugins”).
- **Attributes used for searching sessions**: User's attributes used
for searching sessions in backend if ``whatToTrace`` fails. Useful
to look for sessions by mail or givenName. Let it blank to search
by ``whatToTrace`` only.
by ``whatToTrace`` only
- **Display computed sessions**: Rule to define which users can display a
computed session if no SSO session is found
- **Display empty headers**: Rule to define which users can display ALL headers
appended by LemonLDAP::NG including empty ones
- **Display normalized headers**: Rule to define which users see headers name sent by
the web server (see RFC3875)
- **Display empty values**: Rule to define which users can display ALL attributes
even empty ones
- **Display persistent session data**: Rule to define which users can display
persistent session data
- **Hidden headers**: Sent headers whose value is masked except for unrestricted users.
Key is a Virtualhost name and value represents a headers list.
Key is a Virtualhost name and value represents a space-separated headers list.
A blank value obfuscates ALL relative Virtualhost sent headers.
Note that just valued hearders are masked.

View File

@ -190,6 +190,33 @@ In this example we have:
'exportedHeaders/test.example.com' 'Auth-User' '$uid' \
'exportedHeaders/test.example.com' 'Auth-Mail' '$mail'
Configure form replay
---------------------
To add form replay on a host, you need to set the catched URI and
the variables to post.
In this example we have:
- Host: test.example.com
- Catched URI: /login.php
- jQuery URL: default
- Variables:
- login: $uid
- password: $_password
::
/usr/share/lemonldap-ng/bin/lemonldap-ng-cli -yes 1 -sep , \
addKey \
post,test.example.com,'/login.php' jqueryUrl default
/usr/share/lemonldap-ng/bin/lemonldap-ng-cli -yes 1 -sep , \
addPostVars \
post,test.example.com,'/login.php' login '$uid' \
post,test.example.com,'/login.php' password '$_password'
Configure LDAP authentication backend
-------------------------------------
@ -331,8 +358,7 @@ URL):
/usr/share/lemonldap-ng/bin/lemonldap-ng-cli -yes 1 \
set \
issuerDBOpenIDConnectActivation 1 \
oidcServiceMetaDataIssuer http://auth.example.com
issuerDBOpenIDConnectActivation 1
Generate keys:
@ -457,6 +483,7 @@ To update the master encryption key:
key 'xxxxxxxxxxxxxxx'
.. _cli-sessions:
Sessions Management
-------------------
@ -480,6 +507,15 @@ Modify session ::
lemonldap-ng-sessions setKey 9684dd2a6489bf2be2fbdd799a8028e3 \
authenticationLevel 1
.. versionadded:: 2.0.10
Delete all sessions by username
::
lemonldap-ng-sessions delete --where uid=dwho
Second Factors management
-------------------------

View File

@ -50,7 +50,7 @@ master_doc = 'start'
# General information about the project.
project = u'LemonLDAP::NG'
copyright = u'2020, LemonLDAP::NG'
copyright = u'2021, LemonLDAP::NG'
author = u'LemonLDAP::NG'
# The version info for the project you're documenting, acts as replacement for

View File

@ -497,24 +497,24 @@ Options
Some options are available:
- Port: used to build redirection URL *(when user is not logged, or for
- **Port**: used to build redirection URL *(when user is not logged, or for
CDA requests)*
- HTTPS: used to build redirection URL
- Maintenance mode: reject all requests with a maintenance message
- Aliases: list of aliases for this virtual host *(avoid to rewrite
- **HTTPS**: used to build redirection URL
- **Maintenance mode**: reject all requests with a maintenance message
- **Aliases**: list of aliases for this virtual host *(avoid to rewrite
rules,...)*
- Access to trace: can be used for overwriting REMOTE_CUSTOM with a custom function.
- **Access to trace**: can be used for overwriting REMOTE_CUSTOM with a custom function.
Provide a comma separated parameters list with custom function path and args.
By example: My::accessToTrace, Doctor, Who
- Type: handler type (normal,
- **Type**: handler type (normal,
:doc:`ServiceToken Handler<servertoserver>`,
:doc:`DevOps Handler<devopshandler>`,...)
- Required authentication level: this option avoids to reject user with
- **Required authentication level**: this option avoids to reject user with
a rule based on ``$_authenticationLevel``. When user has not got the
required level, he is redirected to an upgrade page in the portal.
This default level is required for ALL locations relative to this virtual host.
It can be overrided for each locations.
- ServiceToken timeout: by default, ServiceToken is just valid during 30
- **ServiceToken timeout**: by default, ServiceToken is just valid during 30
seconds. This TTL can be customized for each virtual host.

View File

@ -37,14 +37,14 @@ Go to your gitlab account : https://gitlab.ow2.org/profile/keys
cat ~/.ssh/id_rsa.pub
copy id_rsa.pub content to key section and enter a name into "Title"
tans "Add key" button Test ssh connexion :
Copy id_rsa.pub content to key section and enter a name into "Title" and click "Add key" button.
Test ssh connexion :
::
ssh -T git@gitlab.com
accept messages
Accept messages
Install basic tools
-------------------
@ -52,13 +52,13 @@ Install basic tools
Debian
^^^^^^
*root :*
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
aptitude install libauth-yubikey-webclient-perl libnet-smtp-server-perl libtime-fake-perl libtest-output-perl libtest-pod-perl libtest-leaktrace-perl
cpanm Authen::U2F Authen::U2F::Tester Crypt::U2F::Server::Simple
@ -71,7 +71,7 @@ Debian
Configure Git
^^^^^^^^^^^^^
*user :*
As *user :*
::
@ -85,7 +85,7 @@ Configure Git
Import Project and using Git
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*user :* create directory in directory :
As *user*, create directory in directory:
::
@ -98,7 +98,7 @@ Import Project and using Git
git checkout v2.1 # to change branch
git fetch upstream
*import version branch* *on linux station :*
Import version branch on linux station:
::
@ -107,8 +107,7 @@ Import Project and using Git
git rebase upstream/v2.1 # to align to parent project remote branch
git push # to push to working remote branch
*on gitlab, create working branch, one per thematic* *on linux station
:*
On gitlab, create working branch, one per thematic on linux station:
::
@ -142,6 +141,12 @@ For SAML:
Working Project
---------------
Configure hosts file
^^^^^^^^^^^^^^^^^^^^
::
echo '127.0.0.1 auth.example.com manager.example.com test1.example.com test2.example.com' >> /etc/hosts
Unit tests
^^^^^^^^^^

View File

@ -0,0 +1,28 @@
CrowdSec
========
Presentation
------------
`CrowdSec <https://crowdsec.net>`__ is a free and open-source security
automation tool leveraging local IP behavior detection and a
community-powered IP reputation system.
LL::NG provides a **CrowdSec** bouncer that can reject Crowdsec banned-IP
requests or just provide an environment variable that can be used in
another plugin rule. For example, a second factor may be required if user's
IP is CrowdSec-banned.
Configuration
-------------
To configure bouncer plugin, go in ``General Parameters`` > ``Plugins`` >
``CrowdSec``.
You can then configure:
- **Activation**: enable this plugin *(default: disabled)*
- **Action**: reject **or** warn and set ``$env->{CROWDSEC_REJECT} = 1``
- **Base URL of local API**: base URL of CrowdSec local API
*(default: http://localhost:8080)*
- **API key**: API key, usually given by ``cscli bouncers add mylemon``

View File

@ -0,0 +1,168 @@
Documentation
=============
Presentation
------------
|image0|
- :doc:`How it works <presentation>`
- :doc:`Main features <features>`
- :doc:`Quick start tutorial <quickstart>`
Workshops
---------
- LDAPCon 2019: `Connect LL::NG to OpenLDAP and use 2FA, configure SSO
on Fusion Directory and
Dokuwiki <https://github.com/Worteks/ldapcon2019-llng-workshop>`__
- Pass the SALT 2019: `Connect LL::NG to OpenLDAP and use 2FA,
configure SSO on Fusion
Directory <https://github.com/LemonLDAPNG/pts2019-llng-workshop>`__
Installation and configuration
------------------------------
|image1|
- Maintained versions:
- `Version 3.0 </documentation/3.0/>`__ (dev)
- `Version 2.0 </documentation/2.0/>`__ (stable)
- `Version 1.9 </documentation/1.9/>`__ (oldstable)
- Archived versions (unmaintained by `LLNG Team </team>`__ )
- `Version 1.4 </documentation/1.4/>`__
- `Version 1.3 </documentation/1.3/>`__
- `Version 1.2 </documentation/1.2/>`__
- `Version 1.1 </documentation/1.1/>`__
- `Version 1.0 </documentation/1.0/>`__
Packaged versions
~~~~~~~~~~~~~~~~~
These versions are maintained under distribution umbrella following
their policy.
Debian
^^^^^^
<note tip>Following Debian Policy, LLNG packages are never upgraded in
published distributions. However, security patches are backported by
maintenance teams *(except minor ones)*.</note>
=========== ======================== ======================================== ===================================================== ============================================================ =============================== =============================================================
Debian dist LLNG version Secured Maintenance LTS Limit `Extended LTS <https://wiki.debian.org/LTS/Extended>`__ Limit
=========== ======================== ======================================== ===================================================== ============================================================ =============================== =============================================================
*6* *Squeeze* *0.9.4.1* |maybe| No known vulnerability *None* *February 2016* *April 2019*
**7** Wheezy `1.1.2 </documentation/1.1/>`__ |maybe| No known vulnerability **None** [1]_ May 2018 Probably 2021
**8** Jessie `1.3.3 </documentation/1.3/>`__ |clean| CVE-2019-19791 tagged as minor **None** [1]_ June 2020 Probably 2023
**9** Stretch `1.9.7 </documentation/1.9/>`__ |clean| CVE-2019-19791 tagged as minor `Debian LTS Team <https://www.debian.org/lts/>`__ June 2022
\ *Stretch-backports* `2.0.2 </documentation/2.0/>`__ |bad| CVE-2019-12046, CVE-2019-13031, CVE-2019-15941 *None* *June 2019*
\ Stretch-backports-sloppy `2.0.11 </documentation/2.0/>`__ |clean| `LLNG Team </team>`__, "best effort" [3]_ Until Debian 11 release [4]_
**10** Buster `2.0.2 </documentation/2.0/>`__ |clean| CVE-2019-19791 tagged as minor `Debian Security Team <https://security-team.debian.org/>`__ Probably July 2024
\ Buster-backports `2.0.11 </documentation/2.0/>`__ |clean| `LLNG Team </team>`__ Until Debian 11 release [4]_
**Next** Testing Latest [5]_ |clean| `LLNG Team </team>`__
=========== ======================== ======================================== ===================================================== ============================================================ =============================== =============================================================
See `Debian Security
Tracker <https://security-tracker.debian.org/tracker/source-package/lemonldap-ng>`__
and `Debian Package
Tracker <https://tracker.debian.org/pkg/lemonldap-ng>`__ for more.
Ubuntu
^^^^^^
<note warning>Ubuntu version are included in "universe" branch [8]_, so
not really security maintained. Prefer to use our repositories or Debian
ones</note>
=========== ============= ================================ ==================================================================== ===========
Ubuntu dist LLNG version Secured Maintenance
=========== ============= ================================ ==================================================================== ===========
12.04 Precise `1.1.2 </documentation/1.1/>`__ |maybe| No known vulnerability None
14.04 Trusty `1.2.5 </documentation/1.2/>`__ |maybe| No known vulnerability None
16.04 Xenial [9]_ `1.4.6 </documentation/1.4/>`__ |bad| CVE-2019-12046, CVE-2019-13031 None
18.04 Bionic [9]_ `1.9.16 </documentation/1.9/>`__ |bad| CVE-2019-12046, CVE-2019-13031, CVE-2020-24660 None
18.10 Cosmic `1.9.17 </documentation/1.9/>`__ |bad| CVE-2019-12046, CVE-2019-13031, CVE-2020-24660 None
19.04 Disco `2.0.2 </documentation/2.0/>`__ |bad| CVE-2019-12046, CVE-2019-13031, CVE-2019-15941, CVE-2020-24660 None
19.10 Eoan `2.0.5 </documentation/2.0/>`__ |bad| CVE-2019-15941, CVE-2020-24660 None
20.04 Focal [9]_ `2.0.7 </documentation/2.0/>`__ |bad| CVE-2020-24660 None
20.10 Groovy `2.0.8 </documentation/2.0/>`__ |bad| CVE-2020-24660 None
=========== ============= ================================ ==================================================================== ===========
Bug report
----------
See :doc:`Reporting a bug <bugreport>`.
Development
-----------
|image13|
- `Bugtracker <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues>`__
- `Source
code <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/tree/master>`__
- `Nightly trunk builds <http://lemonldap-ng.ow2.io/lemonldap-ng/>`__
*(for Debian or Ubuntu,*\ **really unstable**\ *)*
- Git access:
::
git clone https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng.git
- CPAN test reports:
- `LemonLDAP::NG
Common <http://www.cpantesters.org/distro/L/Lemonldap-NG-Common.html>`__
- `LemonLDAP::NG
Handler <http://www.cpantesters.org/distro/L/Lemonldap-NG-Handler.html>`__
- `LemonLDAP::NG
Portal <http://www.cpantesters.org/distro/L/Lemonldap-NG-Portal.html>`__
- `LemonLDAP::NG
Manager <http://www.cpantesters.org/distro/L/Lemonldap-NG-Manager.html>`__
Other
-----
|image14|
- `Conferences </documentation/conferences>`__
- `References </references>`__
- `Press </press>`__
.. [1]
Possible `Extended LTS <https://wiki.debian.org/LTS/Extended>`__
.. [3]
updated by `LLNG Team </team>`__ until dependencies are compatible
.. [4]
around June 2021
.. [5]
few days after release
.. [8]
Ubuntu universe/multiverse branches are community maintained *(so not
maintained by Canonical)*, but in fact nobody considers LLNG security
issues. See `this
issue <https://bugs.launchpad.net/ubuntu/+source/lemonldap-ng/+bug/1829016>`__
for example
.. [9]
LTS
.. |clean| image:: /icons/clean.png
:width: 20px
.. |bad| image:: /icons/bad.png
:width: 20px
.. |maybe| image:: /icons/maybe.png
:width: 20px
.. |image0| image:: /icons/tutorials.png
.. |image1| image:: /icons/windowlist.png
.. |image13| image:: /icons/terminal.png
.. |image14| image:: /icons/wizard.png

View File

@ -5,7 +5,7 @@ Release notes
-------------
Release notes for latest version:
https://projects.ow2.org/view/lemonldap-ng/lemonldap-ng-2-0-8-is-out/
https://projects.ow2.org/view/lemonldap-ng/lemonldap-ng-2-0-9-is-out
Go on https://projects.ow2.org/bin/view/lemonldap-ng/ for older
versions.
@ -15,13 +15,13 @@ See also :doc:`upgrade notes<upgrade>`.
Packages and archives
---------------------
Stable version (2.0.8)
Stable version (2.0.9)
~~~~~~~~~~~~~~~~~~~~~~
Tarball
^^^^^^^
- `Tarball <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.8.tar.gz>`__
- `Tarball <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.9.tar.gz>`__
RPM
^^^
@ -38,17 +38,17 @@ RHEL/CentOS 7
'''''''''''''
- `RPM
bundle <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.8_el7.rpm.tar.gz>`__
bundle <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.9_el7.rpm.tar.gz>`__
- `Source
RPM <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.8-1.el7.src.rpm>`__
RPM <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.9-1.el7.src.rpm>`__
RHEL/CentOS 8
'''''''''''''
- `RPM
bundle <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.8_el8.rpm.tar.gz>`__
bundle <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.9_el8.rpm.tar.gz>`__
- `Source
RPM <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.8-1.el8.src.rpm>`__
RPM <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.9-1.el8.src.rpm>`__
Debian
^^^^^^
@ -67,7 +67,7 @@ Debian
- `DEB
bundle <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.8_deb.tar.gz>`__
bundle <https://release.ow2.org/lemonldap/lemonldap-ng-2.0.9_deb.tar.gz>`__
Docker
^^^^^^

View File

@ -29,6 +29,7 @@ Inside this jail, you can access to:
* checkDate_
* checkLogonHours_
* date_
* dateToTime_ (|new| in version 2.0.12)
* encrypt_
* groupMatch_
* has2f_ (|new| in version 2.0.10)
@ -58,12 +59,43 @@ date
Returns the date, in format YYYYMMDDHHMMSS, local time by default, GMT
by calling ``date(1)``
::
For example: date(1) lt '19551018080000'
dateToTime
~~~~~~~~~~
.. versionadded:: 2.0.12
Converts a string date into epoch time.
The date format is the LDAP date syntax, for example for the 1st March
2009 (GMT):
::
20090301000000Z
The date may end with a differential timezone that is interpreted to
adjust the epoch time, for example for the 1st March 2009 (+0100):
::
20090301000000+0100
Simple usage example:
::
dateToTime($ssoStartDate) lt dateToTime(date(1))
checkLogonHours
~~~~~~~~~~~~~~~
This function will check the day and the hour of current request, and
compare it to allowed days and hours. It returns 1 if this match, 0
else. All e By default, the allowed days and hours is an hexadecimal
else. By default, the allowed days and hours is an hexadecimal
value, representing each hour of the week. A day has 24 hours, and a
week 7 days, so the value contains 168 bits, converted into 42
hexadecimal characters. Sunday is the first day.
@ -98,7 +130,6 @@ If you use the binary value (Active Directory), use this:
::
All e
checkLogonHours($ssoLogonHours, 'octetstring')
You can also configure jetlag (if all of your users use the same
@ -125,6 +156,7 @@ rejected. You can allow these users instead of reject them:
checkLogonHours($ssoLogonHours, '', '', '1')
checkDate
~~~~~~~~~
@ -132,17 +164,27 @@ This function will check the date of current request, and compare it to
a start date and an end date. It returns 1 if this match, 0 else.
The date format is the LDAP date syntax, for example for the 1st March
2009:
The date format is the LDAP date syntax, for example for the 1st of March
2009 (GMT)
::
20090301000000Z
|new| Since version 2.0.12, the date may end with a differential timezone,
for example for the 1st of March 2009 (+0100):
::
20090301000000+0100
Functions parameters:
- **start**: Start date (GMT)
- **end**: End date (GMT)
- **start**: Start date (GMT unless, |new| since version 2.0.12, a
differential timezone is included)
- **end**: End date (GMT unless, |new| since version 2.0.12, a
differential timezone is included)
- **default_access** (optional): what result to return if **start** and
**end** are empty
@ -152,10 +194,10 @@ Simple usage example:
checkDate($ssoStartDate, $ssoEndDate)
basic
~~~~~
.. attention::
This function is not compliant with
@ -177,6 +219,7 @@ Simple usage example:
basic($uid,$_password)
unicode2iso
~~~~~~~~~~~

View File

@ -14,13 +14,13 @@ LL::NG is designed using `ModelViewController software
architecture <http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller>`__,
so you just have to
:doc:`change HTML/CSS files<portalcustom>` to
custom portal.
customize the portal.
Easy to integrate
-----------------
:doc:`Integrating applications<applications>` in
LL::NG is easy since its dialog with applications is based on
LL::NG is easy since its dialogue with applications is based on
:ref:`customizable HTTP headers<headers>`.
Unifying authentications (Identity Federation)
@ -32,7 +32,7 @@ heterogeneous architecture. LL:NG can be set as Identity provider,
Service Provider or Protocol Proxy
(:doc:`LL::NG as federation protocol proxy<federationproxy>`).
Its SOAP API can also be used to dialog directly with your custom
Its SOAP API can also be used to dialogue directly with your custom
applications.
Sessions
@ -48,9 +48,9 @@ opened sessions:
- by users
- by IP *(IPv4 and IPv6)*
- by date
- by double IP (sessions opened by the same user from multiple
computers)
- by date
It can be used to delete a session
@ -61,7 +61,7 @@ Session restrictions
By default, a user can open several
:doc:`sessions<sessions>`. LL::NG can restrict
this:
the following:
- Allow only one session per user
- Allow only one IP address per user
@ -78,11 +78,11 @@ LL::NG can be configured to provides
- one secured (SSL only) for sensitive applications
- one unsecured for other applications
So if the http cookie is stolen, sensitive applications stay secured.
So that if the http cookie is stolen, sensitive applications remain secured.
Notifications
-------------
LL::NG can be used to prompt users with a message. This can be used to
notify right changes,... See
:doc:`notifications<notifications>` for more.
LL::NG can be used to notify users with a message when authenticating. This can be used to
inform of a change in access rights, the publication of a new IT charter, etc. (See
:doc:`notifications<notifications>` for more details)

View File

@ -0,0 +1,57 @@
|image0|
Find user plugin
================
This plugin allows unauthenticated users to search for an user account to impersonate. This may be useful to randomly provide an
identifier depending on allowed searching attributes and excluded values.
.. attention::
FindUser plugin works only if :doc:`Impersonation plugin<impersonation>` is enabled.
Configuration
-------------
Just enable it in the Manager (section “plugins”). Then, set searching attributes used for selecting accounts and randomly suggest one of them in login form. Excluding attributes can also be defined to exclude some user accounts and avoid to provide them.
- **Parameters**:
- **Activation**: Enable / Disable this plugin
- **Character used as wildcard**: Character that can be used by users as wildcard. An empty value disable wildcarded search requests
- **Parameters control**: Regular expression used for checking searching values syntax
- **Searching attributes**: For each attribute, you have to set a key (attribute as defined in UserBD) and a value that will be display in login form (placeholder). A value can be a multivalued list separated by multiValuesSeparator parameter (General Parameters > Advanced parameters > Separator). See note below.
- **Excluding attributes**: You can defined here attributes used for excluding accounts. Set keys corresponding to UserBD attributes and values to exclude. A value can be a multivalued list separated by multiValuesSeparator parameter (General Parameters > Advanced parameters > Separator)
.. note::
You can provide a 'multiValuesSeparator' separated list of allowed searching values that will be displayed as an HTML <select> list ::
attribute#placeholder[#empty] => value1; placeholder1; value2; placeholder2
For example ::
uid#Identity => dwho; Dr Who; rtyler; Rose Tyler; msmith; Mr Smith
uid#Identity#1 => dwho; Dr Who; rtyler; Rose Tyler (allow empty value)
Entries are sorted by alphabetical order.
.. attention::
Searching request is built based on provided parameters value depending on users backend like this:
request => searchAttr1=value && searchAttr2=value && not excludeAttr1=value && not excludeAttr2=value
.. danger::
This plugin works only with a users backend and the searching or excluding attributes must exist.
.. danger::
With AuthChoice, you must set which module will be called by this plugin (:doc:`Backend choice by users<authchoice>`).
.. |image0| image:: /documentation/beta.png
:width: 100px

256
doc/sources/admin/hooks.rst Normal file
View File

@ -0,0 +1,256 @@
Available plugin hooks
======================
OpenID Connect Issuer hooks
---------------------------
oidcGotRequest
~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG received an authorization request on the `/oauth2/authorize` endpoint.
The hook's parameter is a hash containing the authorization request parameters.
Sample code::
use constant hook => {
oidcGotRequest => 'addScopeToRequest',
};
sub addScopeToRequest {
my ( $self, $req, $oidc_request ) = @_;
$oidc_request->{scope} = $oidc_request->{scope} . " my_hooked_scope";
return PE_OK;
}
oidcGotClientCredentialsGrant
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.12
This hook is triggered when LemonLDAP::NG successfully authorized a :ref:`Client Credentials Grant <client-credentials-grant>`.
The hook's parameters are:
* A hash of the current session info
* the configuration key of the relying party which is being identified
Sample code::
use constant hook => {
oidcGotClientCredentialsGrant => 'addSessionVariable',
};
sub addSessionVariable {
my ( $self, $req, $info, $rp ) = @_;
$info->{is_client_credentials} = 1;
return PE_OK;
}
oidcGenerateUserInfoResponse
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG is about to send a UserInfo response to a relying party on the `/oauth2/userinfo` endpoint.
The hook's parameter is a hash containing all the claims that are about to be released.
Sample code::
use constant hook => {
oidcGenerateUserInfoResponse => 'addClaimToUserInfo',
};
sub addClaimToUserInfo {
my ( $self, $req, $userinfo ) = @_;
$userinfo->{"userinfo_hook"} = 1;
return PE_OK;
}
oidcGenerateIDToken
~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG is generating an ID Token.
The hook's parameters are:
* A hash of the claims to be contained in the ID Token
* the configuration key of the relying party which will receive the token
Sample code::
use constant hook => {
oidcGenerateIDToken => 'addClaimToIDToken',
};
sub addClaimToIDToken {
my ( $self, $req, $payload, $rp ) = @_;
$payload->{"id_token_hook"} = 1;
return PE_OK;
}
oidcGenerateAccessToken
~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.12
This hook is triggered when LemonLDAP::NG is generating an JWT-formatted Access Token
The hook's parameters are:
* A hash of the claims to be contained in the Access Token
* the configuration key of the relying party which will receive the token
Sample code::
use constant hook => {
oidcGenerateAccessToken => 'addClaimToAccessToken',
};
sub addClaimToAccessToken {
my ( $self, $req, $payload, $rp ) = @_;
$payload->{"access_token_hook"} = 1;
return PE_OK;
}
oidcResolveScope
~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.12
This hook is triggered when LemonLDAP::NG is resolving scopes.
The hook's parameters are:
* An array ref of currently granted scopes, which you can modify
* The configuration key of the requested RP
Sample code::
use constant hook => {
oidcResolveScope => 'addHardcodedScope',
};
sub addHardcodedScope{
my ( $self, $req, $scopeList, $rp ) = @_;
push @{$scopeList}, "myscope";
return PE_OK;
}
SAML Issuer hooks
-----------------
samlGotAuthnRequest
~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG has received a SAML login request
The hook's parameter is the Lasso::Login object
Sample code::
use constant hook => {
samlGotAuthnRequest => 'gotRequest',
};
sub gotRequest {
my ( $self, $res, $login ) = @_;
# Your code here
}
samlBuildAuthnResponse
~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG is about to build a response to the SAML login request
The hook's parameter is the Lasso::Login object
Sample code::
use constant hook => {
samlBuildAuthnResponse => 'buildResponse',
};
sub buildResponse {
my ( $self, $res, $login ) = @_;
# Your code here
}
samlGotLogoutRequest
~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG has received a SAML logout request
The hook's parameter is the Lasso::Logout object
Sample code::
use constant hook => {
samlGotLogoutRequest => 'gotLogout',
};
sub gotLogout {
my ( $self, $res, $logout ) = @_;
# Your code here
}
samlGotLogoutResponse
~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG has received a SAML logout response
The hook's parameter is the Lasso::Logout object
Sample code::
use constant hook => {
samlGotLogoutResponse => 'gotLogoutResponse',
};
sub gotLogoutResponse {
my ( $self, $res, $logout ) = @_;
# Your code here
}
samlBuildLogoutResponse
~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 2.0.10
This hook is triggered when LemonLDAP::NG is about to generate a SAML logout response
The hook's parameter is the Lasso::Logout object
Sample code::
use constant hook => {
samlBuildLogoutResponse => 'buildLogoutResponse',
};
sub buildLogoutResponse {
my ( $self, $res, $logout ) = @_;
# Your code here
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -106,7 +106,7 @@ Options
^^^^^^^
- **Service URL** : the service (user-facing) URL of the CAS-enabled
application.
application. See :ref:`idpcas-url-matching`
- **User attribute** : session field that will be used as main
identifier.
- **Authentication Level** : required authentication level to access this
@ -125,3 +125,21 @@ Macros
You can define here macros that will be only evaluated for this service,
and not registered in the session of the user.
.. _idpcas-url-matching:
URL Matching
^^^^^^^^^^^^
.. versionchanged:: 2.0.10
Before version 2.0.10, only the hostname was taken into account, which made it impossible to have two different CAS services behind the same hostname.
Since version 2.0.10, the entire service URL is compared to the Service URL defined in LemonLDAP::NG. The longest prefix wins.
For example, if you declared two applications in LemonLDAP::NG with the following service URLs:
* https://cas.example.com/applications/zone1
* https://cas.example.com/applications/
An application located at https://cas.example.com/applications/zone1/myapp will match the first CAS service definition

View File

@ -166,6 +166,8 @@ claim <http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims>`__.
.. include:: openidconnectclaims.rst
.. _oidcexportedattr:
For each OpenID Connect claim you want to release to applications, you can define:
* **Claim name**: the name of the claim as it will appear in Userinfo responses
@ -214,6 +216,41 @@ Userinfo endpoint.
LemonLDAP::NG session attribute in the **Exported Attributes**
section
Scope Rules
^^^^^^^^^^^
.. versionadded:: 2.0.12
|beta| This feature may change in a future version in a way that breaks
compatibility with existing configuration
By default, LemonLDAP::NG grants all scopes requested by the application, as
long as the user consents to them.
This configuration screen allows you to change that behavior by attaching
:ref:`a rule<rules>` to a particular scope.
* If the rule evaluates to true, the scope is added to the current request,
even if it was not requested by the application
* If the rule evaluates to false, the scope is removed from the current request
* Scopes which are not declared in the "Scope rules" list are left untouched
When writing scope rules, you can use the special ``$requested`` variable. This
variables evaluates to `true` within a scope rule when the corresponding scope
has been requested by the application. You can use this variable in a dynamic
rule when you only want to add a scope when the application requested it.
Examples:
* ``read``: ``inGroup('readers')``
* the ``read`` scope will be granted if the user is a member of the ``readers`` group even if the application did not request it.
* ``write``: ``$requested and inGroup('writers')``
* the ``write`` scope will be granted if the user is a member of the ``writers`` group, but only if the application requested it.
Options
^^^^^^^
@ -238,6 +275,13 @@ Options
- **Force claims to be returned in ID Token**: This options will
make user attributes from the requested scope appear as ID Token
claims.
- **Use JWT format for Access Token** (since version ``2.0.12``): When
using this option, Access Tokens will use the JWT format, which means they
can be verified by external OAuth2.0 resource servers without using the
introspection or userinfo endpoint.
- **Release claims in Access Token** (since version ``2.0.12``): If Access
Tokens are in JWT format, this option lets you release the claims defined
in the *Extra Claims* section inside the Access Token itself.
- **Additional audiences** (since version ``2.0.8``): You can
specify a space-separate list of audiences that will be added the
audiences of the ID Token
@ -253,8 +297,8 @@ Options
default value is one minute.
- **ID Token expiration**: Expiration time of ID Tokens. The default
value is one hour.
- **Access token expiration**: Expiration time of Access Tokens. The
default value is one hour.
- **Access token expiration** (since version ``2.0.12``): Expiration time
of Access Tokens. The default value is one hour.
- **Offline session expiration**: This sets the lifetime of the
refresh token obtained with the **offline_access** scope. The
default value is one month. This parameter only applies if offline
@ -262,8 +306,10 @@ Options
- **Security**
- **ID Token signature algorithm**: Select one of ``none``,
``HS256``, ``HS384``, ``HS512``, ``RS256``, ``RS384``, ``RS512``
- **ID Token signature algorithm**: Select one of the available public key
(RSXXX) or HMAC (HSXXX) based signature algorithms
- **Access Token signature algorithm**: Select one of the available public
key signature algorithms
- **Require PKCE** (since version ``2.0.4``): a code challenge is
required at token endpoint (see
`RFC7636 <https://tools.ietf.org/html/rfc7636>`__)
@ -274,7 +320,8 @@ Options
https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
for details. These offline sessions can be administered through
the Session Browser.
- **Allow OAuth2.0 Password Grant** (since version ``2.0.8``): Allow the use of the Resource Owner Password Credentials Grant on by this client. This feature only works if you have configured a form-based authentication module.
- **Allow OAuth2.0 Password Grant** (since version ``2.0.8``): Allow the use of the :ref:`Resource Owner Password Credentials Grant <resource-owner-password-grant>` by this client. This feature only works if you have configured a form-based authentication module.
- **Allow OAuth2.0 Client Credentials Grant** (since version ``2.0.11``): Allow the use of the :ref:`Client Credentials Grant <client-credentials-grant>` by this client.
- **Authentication Level**: required authentication level to access this application
- **Access Rule**: lets you specify a :doc:`Perl rule<rules_examples>` to restrict access to this client
@ -285,6 +332,45 @@ Options
- **Type**: Type of Logout to perform (only Front-Channel is implemented for now)
- **Session required**: Whether to send the Session ID in the logout request
.. _resource-owner-password-grant:
Resource Owner Password Credentials Grant
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Resource Owner Password Credentials Grant allows you to exchange a user's login and password for an access token. This must be considered a legacy form of authentication, since the Authorization Code web-based flow is prefered for all applications that support it. It can however be useful in some scenarios involving technical accounts that cannot implement a web-based authentication flow.
.. seealso::
`Specification for the Resource Owner Password Credentials Grant <https://tools.ietf.org/html/rfc6749#section-4.3>`__
.. _client-credentials-grant:
Client Credentials Grant
^^^^^^^^^^^^^^^^^^^^^^^^
The Client Credentials Grant allows you to obtain an Access Token using only a Relying Party's Client ID and Client Secret.
The following attributes are made available in the created session:
* The ``_whatToTrace`` attribute (main session identifier), is set to the
relying party's configuration key
* The ``_scope`` attribute is set to the requested scopes
* The ``_clientId`` attribute is set to the Client ID that obtained the access
token.
* The ``_clientConfKey`` attribute is set to the LemonLDAP::NG configuration
key for the client that obtained the access token.
The Access Rule, if defined, will have access to those variables, as well as
the `@ENV` array. You can use it to restrict the use of this grant to
pre-determined scopes, a particular IP address, etc.
These session attribute will be released on the UserInfo endpoint if they are
mapped to Exported Attributes and Extra Claims
.. seealso::
`Specification for the Client Credentials Grant <https://tools.ietf.org/html/rfc6749#section-4.4>`__
Macros
^^^^^^
@ -296,3 +382,5 @@ Display
- **Display name**: Name of the RP application
- **Logo**: Logo of the RP application
.. |beta| image:: /documentation/beta.png

View File

@ -154,11 +154,13 @@ Signature
These options override service signature options (see
:ref:`SAML service configuration<samlservice-general-options>`).
- **Signature method**: signature method for messages sent to this service
- **Sign SSO message**: sign SSO message
- **Check SSO message signature**: check SSO message signature
- **Sign SLO message**: sign SLO message
- **Check SLO message signature**: check SLO message signature
- **Signature method**: the algorithm used to sign messages sent to this service
- **Sign SSO message**
- **Check SSO message signature**: "On" means that LemonLDAP::NG will verify
signatures if IDP and SP metadata require it. "Off" will disable signature
verification entirely.
- **Sign SLO message**
- **Check SLO message signature**
Security
''''''''
@ -170,21 +172,38 @@ Security
- **Authentication Level**: required authentication level to access this SP
- **Access Rule**: lets you specify a :doc:`Perl rule<rules_examples>` to restrict access to this SP
Extra variables
^^^^^^^^^^^^^^^
.. tip::
The following environment variables are available in SAML access rules and macros:
The IDP Initiated URL is the SSO SAML URL with GET
parameters:
* ``$env->{llng_saml_sp}`` : entityID of the SAML service
* ``$env->{llng_saml_spconfkey}`` : configuration key of the SAML service
- IDPInitiated: 1
- One of:
.. versionadded:: 2.0.10
- sp: SP entity ID
- spConfKey: SP configuration key
* ``$env->{llng_saml_acs}`` : AssertionConsumerServiceURL, if specified in the AuthnRequest
For example:
http://auth.example.com/saml/singleSignOn?IDPInitiated=1&spConfKey=simplesamlphp
IDP Initiated mode
^^^^^^^^^^^^^^^^^^
The IDP Initiated URL is the SSO SAML URL with GET
parameters:
- ``IDPInitiated``: ``1``
- One of:
- ``sp``: Service Provider entity ID
- ``spConfKey``: Service Provider configuration key
For example:
http://auth.example.com/saml/singleSignOn?IDPInitiated=1&spConfKey=simplesamlphp
- Optionally, if you may also specify, in addition to ``sp`` or ``spConfKey``:
- ``spDest``: URL of Service Provider's AssertionConsumerService
The URL specified in ``spDest`` *must* be present in the Service Provider metadata registered in LemonLDAP::NG. This is only useful if your Service Provider is reachable over multiple URLs.
Macros
^^^^^^

View File

@ -7,4 +7,5 @@ Development
bugreport
contribute
handlerarch
plugincustom
customhandlers

View File

@ -17,3 +17,4 @@ Mini Howtos
renater
behindproxyminihowto
useoutgoingproxy
testopenidconnect

View File

@ -8,17 +8,19 @@ Plugins
autosignin
bruteforceprotection
cda
checkdevops
checkstate
checkuser
crowdsec
viewer
contextswitching
plugincustom
decryptvalue
loginhistory
forcereauthn
globallogout
grantsession
impersonation
finduser
notifications
status
public_pages

View File

@ -6,7 +6,6 @@ Sessions database
changesessionbackend
filesessionbackend
restsessionbackend
sqlsessionbackend
ldapsessionbackend
nosqlsessionbackend

View File

@ -25,6 +25,7 @@ LemonLDAP::NG provides packages for Red Hat/Centos 7:
- lemonldap-ng-fastcgi-server: FastCGI server needed to use Nginx
- lemonldap-ng-nginx: contains Nginx configuration and dependencies
- lemonldap-ng-uwsgi-app: contains Uwsgi application
- lemonldap-ng-selinux: contains the SELinux policy for httpd
- perl-Lemonldap-NG-Common: CPAN - Shared modules
- perl-Lemonldap-NG-Handler: CPAN - Handler modules
- perl-Lemonldap-NG-Manager: CPAN - Manager modules
@ -124,6 +125,9 @@ If the packages are stored in a yum repository:
yum install lemonldap-ng
# If you use SELinux
yum install lemonldap-ng-selinux
You can also use yum on local RPMs file:
::

View File

@ -30,9 +30,9 @@ Name Comment Example
**sentinels** Redis sentinels list 127.0.0.1:26379,127.0.0.2:26379,127.0.0.3:26379
**password** password (== requirepass) ChangeMe
**select** Redis DB 1
**Index** Fields to index refer to :ref:`fieldstoindex`
============= =========================== ===============================================
Security
--------

View File

@ -39,6 +39,23 @@ Example:
user: "dwho"
}
Additional variables
--------------------
The OAuth2 handler defines a few extra variables that you can use in
:doc:`rules and headers<writingrulesand_headers>`.
* ``$_clientId``: client ID of the application which requested the Access Token
* ``$_clientConfKey``: configuration key of the application which requested the
Access Token
* ``$_scope``: list of space-separated scopes granted by the Access Token
For example, to grant access to access tokens containing the ``write`` scope,
use ::
$_scope =~ /(?<!\S)write(?!\S)/
Configuration
-------------

View File

@ -41,8 +41,8 @@ level.
Security
~~~~~~~~
- **Keys** : define public/private key pair to do asymmetric signature
- **Signing Key ID**: ID of signing key
- **Keys** : define public/private key pair to do asymmetric signature. A JWKS
``kid`` (Key ID) is automatically derived when generating new keys.
- **Dynamic Registration**: Set to 1 to allow clients to register
themselves. This may be a security risk as this will create a new
configuration in the backend per registration request. You can limit

View File

@ -28,23 +28,26 @@ SSLAuthnLevel SSL authentication level
SSLVar ✔
SSLVarIf ✔
activeTimer Enable timers on portal pages ✔
adaptativeAuthenticationLevelRules Adaptative authentication level rules ✔
apacheAuthnLevel Apache authentication level ✔
applicationList Applications list ✔
authChoiceAuthBasic Auth module used by AuthBasic handler ✔
authChoiceFindUser Auth module used by FindUser plugin ✔
authChoiceModules Hash list of Choice strings ✔
authChoiceParam Applications list ✔
authentication Authentication module ✔
autoSigninRules List of auto signin rules ✔
available2F Available second factor modules ✔ ✔
available2FSelfRegistration Available self-registration modules for second factor ✔ ✔
avoidAssignment Avoid assignment in expressions ✔ ✔
browsersDontStorePassword Avoid browsers to store users password ✔
bruteForceProtection Enable brute force attack protection ✔
bruteForceProtectionIncrementalTempo Enable incremental lock time for brute force attack protection ✔
bruteForceProtectionLockTimes Incremental lock time values for brute force attack protection ✔
bruteForceProtectionMaxAge Brute force attack protection -> Max age between last and first allowed failed login ✔ ✔
bruteForceProtectionMaxFailed Brute force attack protection -> Max allowed failed login ✔
bruteForceProtectionMaxLockTime Brute force attack protection -> Max lock time ✔ ✔
bruteForceProtectionTempo Brute force attack protection -> Tempo before try again
bruteForceProtectionMaxAge Max age between current and first failed login ✔ ✔
bruteForceProtectionMaxFailed Max allowed failed login
bruteForceProtectionMaxLockTime Max lock time ✔ ✔
bruteForceProtectionTempo Lock time
captcha_login_enabled Captcha on login page ✔
captcha_mail_enabled Captcha on password reset page ✔
captcha_register_enabled Captcha on account creation page ✔
@ -76,10 +79,13 @@ checkState Enable CheckState plugin
checkStateSecret Secret token for CheckState plugin ✔
checkTime Timeout to check new configuration in local cache ✔ ✔ ✔
checkUser Enable check user ✔
checkUserDisplayComputedSession Display empty headers rule ✔
checkUserDisplayEmptyHeaders Display empty headers rule ✔
checkUserDisplayEmptyValues Display session empty values rule ✔
checkUserDisplayNormalizedHeaders Display normalized headers rule ✔
checkUserDisplayPersistentInfo Display persistent session info rule ✔
checkUserHiddenAttributes Attributes to hide in CheckUser plugin ✔
checkUserHiddenHeaders Header values to hide if not empty ✔
checkUserIdRule checkUser identities rule ✔
checkUserSearchAttributes Attributes used for retrieving sessions in user DataBase ✔
checkUserUnrestrictedUsersRule checkUser unrestricted users rule ✔
@ -89,6 +95,7 @@ combination Combination rule
compactConf Compact configuration ✔
configStorage Configuration storage ✔ ✔ ✔ ✔
confirmFormMethod HTTP method for confirm page form ✔
contextSwitchingAllowed2fModifications Allowed SFA modifications ✔
contextSwitchingIdRule Context switching identities rule ✔
contextSwitchingPrefix Prefix to store real session Id ✔ ✔
contextSwitchingRule Context switching activation rule ✔
@ -143,6 +150,7 @@ decryptValueFunctions Custom function used for
decryptValueRule Decrypt value activation rule ✔
demoExportedVars Demo exported variables ✔
disablePersistentStorage Enabled persistent storage ✔
displaySessionId Display _session_id with sessions explorer ✔
domain DNS domain ✔ ✔
exportedAttr List of attributes to export by SOAP or REST servers ✔
exportedVars Main exported variables ✔
@ -159,6 +167,11 @@ facebookAuthnLevel Facebook authentication
facebookExportedVars Facebook exported variables ✔
facebookUserField ✔
failedLoginNumber Number of failures stored in login history ✔
findUser Enable find user ✔
findUserControl Regular expression to validate parameters ✔
findUserExcludingAttributes Attributes used for excluding accounts ✔
findUserSearchingAttributes Attributes used for searching accounts ✔
findUserWildcard Character used as wildcard ✔
forceGlobalStorageIssuerOTT Force Issuer tokens to be stored into Global Storage ✔ ✔
forceGlobalStorageUpgradeOTT Force Upgrade tokens be stored into Global Storage ✔ ✔
formTimeout Token timeout for forms ✔
@ -210,6 +223,7 @@ issuerDBSAMLRule SAML IDP rule
issuersTimeout Token timeout for issuers ✔
jsRedirect Use javascript for redirections ✔
key Secret key ✔
krbAllowedDomains Allowed domains ✔
krbAuthnLevel Null authentication level ✔
krbByJs Launch Kerberos authentication by Ajax ✔
krbKeytab Kerberos keytab ✔
@ -221,6 +235,7 @@ ldapCAFile Location of the certific
ldapCAPath Location of the CA directory for LDAP connections ✔
ldapChangePasswordAsUser ✔
ldapExportedVars LDAP exported variables ✔
ldapGetUserBeforePasswordChange ✔
ldapGroupAttributeName LDAP attribute name for member in groups ✔
ldapGroupAttributeNameGroup LDAP attribute name in group entry referenced as member in groups ✔
ldapGroupAttributeNameSearch LDAP attributes to search in groups ✔
@ -229,6 +244,7 @@ ldapGroupBase
ldapGroupDecodeSearchedValue Decode value before searching it in LDAP groups ✔
ldapGroupObjectClass LDAP object class of groups ✔
ldapGroupRecursive LDAP recursive search in groups ✔
ldapIOTimeout LDAP operation timeout ✔
ldapITDS Support for IBM Tivoli Directory Server ✔
ldapPasswordResetAttribute LDAP password reset attribute ✔
ldapPasswordResetAttributeValue LDAP password reset value ✔
@ -240,7 +256,6 @@ ldapSearchDeref "deref" param of Net::LD
ldapServer LDAP server (host or URI) ✔
ldapSetPassword ✔
ldapTimeout LDAP connection timeout ✔
ldapIOTimeout LDAP operation timeout ✔
ldapUsePasswordResetAttribute LDAP store reset flag in an attribute ✔
ldapVerify Whether to validate LDAP certificates ✔
ldapVersion LDAP protocol version ✔
@ -268,6 +283,7 @@ mail2fBody Mail body for second fac
mail2fCodeRegex Regular expression to create a mail OTP code ✔
mail2fLabel Portal label for Mail second factor ✔
mail2fLogo Custom logo for Mail 2F ✔
mail2fSessionKey Session parameter where mail is stored ✔
mail2fSubject Mail subject for second factor authentication ✔
mail2fTimeout Second factor code timeout ✔
mailBody Custom password reset mail body ✔
@ -359,6 +375,7 @@ openIdSreg_timezone OpenID SREG timezone ses
pamAuthnLevel PAM authentication level ✔
pamService PAM service ✔
passwordDB Password module ✔
passwordPolicyActivation Enable password policy ✔
passwordPolicyMinDigit Password policy: minimal digit characters ✔
passwordPolicyMinLower Password policy: minimal lower characters ✔
passwordPolicyMinSize Password policy: minimal size ✔
@ -376,14 +393,14 @@ portalAntiFrame Avoid portal to be displ
portalCheckLogins Display login history checkbox in portal ✔
portalCustomCss Path to custom CSS file ✔
portalDisplayAppslist Display applications tab in portal ✔
portalDisplayCertificateResetByMail Display Certificate Reset by mail tab in portal
portalDisplayCertificateResetByMail Display certificate reset by mail button in portal
portalDisplayChangePassword Display password tab in portal ✔
portalDisplayGeneratePassword Display password generate box in reset password form ✔
portalDisplayLoginHistory Display login history tab in portal ✔
portalDisplayLogout Display logout tab in portal ✔
portalDisplayOidcConsents Display OIDC consent tab in portal ✔
portalDisplayPasswordPolicy Display policy in password form ✔
portalDisplayRefreshMyRights Displays the link to refresh the user session ✔
portalDisplayRefreshMyRights Display link to refresh the user session
portalDisplayRegister Display register button in portal ✔
portalDisplayResetPassword Display reset password button in portal ✔
portalErrorOnExpiredSession Show error if session is expired ✔
@ -444,6 +461,7 @@ restAuthnLevel REST authentication leve
restClockTolerance How tolerant the REST session server will be to clock dift ✔
restConfigServer Enable REST config server ✔
restExportSecretKeys Allow to export secret keys in REST session server ✔
restFindUserDBUrl ✔
restPasswordServer Enable REST password reset server ✔
restPwdConfirmUrl ✔
restPwdModifyUrl ✔
@ -543,6 +561,8 @@ sslHost URL for SSL Ajax request
staticPrefix Prefix of static files for HTML templates ✔ ✔
status Status daemon activation ✔ ✔
stayConnected Enable StayConnected plugin ✔
stayConnectedCookieName Name of the stayConnected plugin cookie ✔
stayConnectedTimeout StayConnected persistent connexion session timeout ✔
storePassword Store password in session ✔
successLoginNumber Number of success stored in login history ✔
syslogFacility Syslog logger technical facility ✔ ✔ ✔ ✔

View File

@ -0,0 +1,110 @@
PgJSON session backend
======================
This backend is the recommended one for production installations of LemonLDAP::NG.
Prerequisites
-------------
First, make sure you have installed the ``DBD::Pg`` perl module.
On Debian-based distributions ::
apt install libdbd-pg-perl
On Fedora-based distributions ::
yum install 'perl(DBD::Pg)'
The minimum required version of PostgreSQL is 9.3 with `support for JSON column types <https://www.postgresql.org/docs/9.3/functions-json.html>`__
Make sure you are using at least version 1.2.9 of ``Apache::Session::Browseable``, this might require installing it from Debian Backports or CPAN.
Create database schema
----------------------
Create the following tables. You may skip the session types you are not going to use, but you need at least ``sessions`` and ``psessions``
::
CREATE TABLE sessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX i_s__whatToTrace ON sessions ((a_session ->> '_whatToTrace'));
CREATE INDEX i_s__session_kind ON sessions ((a_session ->> '_session_kind'));
CREATE INDEX i_s__utime ON sessions ((cast (a_session ->> '_utime' as bigint)));
CREATE INDEX i_s_ipAddr ON sessions ((a_session ->> 'ipAddr'));
CREATE INDEX i_s__httpSessionType ON sessions ((a_session ->> '_httpSessionType'));
CREATE INDEX i_s_user ON sessions ((a_session ->> 'user'));
CREATE TABLE psessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX i_p__session_kind ON psessions ((a_session ->> '_session_kind'));
CREATE INDEX i_p__httpSessionType ON psessions ((a_session ->> '_httpSessionType'));
CREATE INDEX i_p__session_uid ON psessions ((a_session ->> '_session_uid'));
CREATE INDEX i_p_ipAddr ON psessions ((a_session ->> 'ipAddr'));
CREATE INDEX i_p__whatToTrace ON psessions ((a_session ->> '_whatToTrace'));
CREATE TABLE samlsessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX i_a__session_kind ON samlsessions ((a_session ->> '_session_kind'));
CREATE INDEX i_a__utime ON samlsessions ((cast(a_session ->> '_utime' as bigint)));
CREATE INDEX i_a_ProxyID ON samlsessions ((a_session ->> 'ProxyID'));
CREATE INDEX i_a__nameID ON samlsessions ((a_session ->> '_nameID'));
CREATE INDEX i_a__assert_id ON samlsessions ((a_session ->> '_assert_id'));
CREATE INDEX i_a__art_id ON samlsessions ((a_session ->> '_art_id'));
CREATE INDEX i_a__saml_id ON samlsessions ((a_session ->> '_saml_id'));
CREATE TABLE oidcsessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX i_o__session_kind ON oidcsessions ((a_session ->> '_session_kind'));
CREATE INDEX i_o__utime ON oidcsessions ((cast(a_session ->> '_utime' as bigint )));
CREATE TABLE cassessions (
id varchar(64) not null primary key,
a_session jsonb
);
CREATE INDEX i_c__session_kind ON cassessions ((a_session ->> '_session_kind'));
CREATE INDEX i_c__utime ON cassessions ((cast(a_session ->> '_utime' as bigint)));
CREATE INDEX i_c__cas_id ON cassessions ((a_session ->> '_cas_id'));
CREATE INDEX i_c_pgtIou ON cassessions ((a_session ->> 'pgtIou'));
LemonLDAP::NG configuration
---------------------------
Go in the Manager and set the session module to ``Apache::Session::Browseable::PgJSON`` for each session type you intend to use:
* ``General parameters`` » ``Sessions`` » ``Session storage`` » ``Apache::Session module``
* ``General parameters`` » ``Sessions`` » ``Persistent sessions`` » ``Apache::Session module``
* ``CAS Service`` » ``CAS sessions module name``
* ``OpenID Connect Service`` » ``Sessions`` » ``Sessions module name``
* ``SAML2 Service`` » ``Advanced`` » ``SAML sessions module name``
Then, set the following module options:
=================== ================================================= =============================================================
Required parameters
=================== ================================================= =============================================================
Name Comment Example
**DataSource** The `DBI <https://metacpan.org/pod/DBI>`__ string dbi:Pg:database=lemonldap-ng
**UserName** The database username lemonldapng
**Password** The database password mysuperpassword
**TableName** Table name (optional) sessions
**Commit** 1 This setting is mandatory for PostgreSQL to work
=================== ================================================= =============================================================
.. tip::
Unlike other browseable modules, Pg::JSON does not require an ``Index`` parameter

View File

@ -4,6 +4,9 @@ Write a custom plugin
Presentation
------------
Standard entry points
~~~~~~~~~~~~~~~~~~~~~
You can now write a custom portal plugin that will hook in the
authentication process:
@ -18,6 +21,9 @@ authentication process:
- ``forAuthUser``: method called for already authenticated users
- ``beforeLogout``: method called before logout
Extended entry points
~~~~~~~~~~~~~~~~~~~~~
If you need to call a method just after any standard method in
authentication process, then use ``afterSub``, for example:
@ -48,6 +54,23 @@ authentication process, then use ``aroundSub``, for example:
return $ret;
}
Hooks
~~~~~
.. versionadded:: 2.0.10
Your plugin can also register itself to be called at some points of interest
within the main LemonLDAP::NG code.
.. toctree::
:maxdepth: 1
hooks
Routes
~~~~~~
The plugin can also define new routes and call actions on them.
See also ``Lemonldap::NG::Portal::Main::Plugin`` man page.

View File

@ -170,9 +170,9 @@ We include some template files that can be customized:
- customhead.tpl : HTML header markups (like CSS, js inclusion)
- customheader.tpl : HTML code in the header
- customfooter.tpm : HTML code in the footer
- customLoginHeader.tpl : HTML code int the login header
- customLoginFooter.tpl : HTML code int the login footer
- customfooter.tpl : HTML code in the footer
- customLoginHeader.tpl : HTML code in the login header
- customLoginFooter.tpl : HTML code in the login footer
To use custom files, copy them into your skin folder:

View File

@ -15,32 +15,33 @@ for several usage:
Configuration
-------------
- **SOAP/REST exported attributes**: list session attributes shared
trough SOAP/REST
- Use ``+`` to append to the default list of technical attributes,
example: ``+ uid mail``
REST
~~~~
Go in ``General Parameters`` > ``Plugins`` > ``Portal servers``:
Go in ``General Parameters`` > ``Plugins`` > ``Portal servers`` > ``REST services``:
- **REST session server**: Enable REST for sessions
- **REST configuration server**: Enable REST for configuration
- **SOAP/REST exported attributes**: list session attributes shared
trough REST
- use ``+`` to append to the default list of technical attributes,
example: ``+ uid mail``
- **Session server**: Enable REST for sessions
- **Configuration server**: Enable REST for configuration
- **Authentication server**: Enable REST for authentication
- **Password reset server**: Enable REST for password reset
- **Server clock tolerance**: Allow a clock drift
- **Export secret attributes**: Secret attributes can be exported
See also :doc:`REST Services<restservices>`.
SOAP *(deprecated)*
~~~~~~~~~~~~~~~~~~~
Go in ``General Parameters`` > ``Plugins`` > ``Portal servers``:
Go in ``General Parameters`` > ``Plugins`` > ``Portal servers`` > ``SOAP services``:
- **SOAP session server**: Enable SOAP for sessions
- **SOAP configuration server**: Enable SOAP for configuration
- **SOAP/REST exported attributes**: list session attributes shared
trough SOAP
- use ``+`` to append to the default list of technical attributes,
example: ``+ uid mail``
- **Session server**: Enable SOAP for sessions
- **Configuration server**: Enable SOAP for configuration
- **WSDL server**: Enable WSDL server
See also :doc:`SOAP Services<soapservices>`.

View File

@ -26,7 +26,7 @@ Main components
`CAS <http://en.wikipedia.org/wiki/Central_Authentication_Service>`__).
Futhermore, Portal affordes many other features (see
:doc:`portal<portal>` for more)
- **Handler**: used to protect applications which can read HTTP headers
- :doc:`Handler<index_handler>`: used to protect applications which can read HTTP headers
or environment variables to get user information
Databases
@ -36,7 +36,7 @@ Databases
.. attention::
We call "database" a backend where we can read or write a data.
This can be a file, an LDAP directory, ...
This can be a file, an LDAP directory, etc.
We split databases in two categories:
@ -130,12 +130,13 @@ Session expiration
~~~~~~~~~~~~~~~~~~
The session expires after 20 hours by default.
This duration can be set in the manager's Configuration tab (General Parameters > Sessions > Sessions Timeout).
.. attention::
- Handlers have a session cache, with a default lifetime of 10 minutes.
So for Handlers on different physical servers than the Portal, a user
with an expired session can still be authorized till the cache
So for Handlers located on different physical servers than the Portal, a user
with an expired session can still be authorized until the cache
expires.
- Sessions are deleted by a scheduled task. Don't forget to install
cron files !

View File

@ -42,6 +42,8 @@ CentOS / RHEL
yum update
yum install epel-release
yum install lemonldap-ng
# If you use SELinux
yum install lemonldap-ng-selinux
SSO domain configuration
------------------------
@ -67,14 +69,15 @@ or change it, for example for ``mydomain.com``:
/etc/apache2/sites-available/*
In order to be able to test, update your DNS or your local ``hosts``
file to map this names to the SSO server IP:
file to map these names to the SSO server IP:
- auth.mydomain.com
- manager.mydomain.com
- test1.mydomain.com
- test2.mydomain.com
For example on your local computer (adjust your server IP and test domain)
For example, you can enter the following command on your local computer:
(adjust according to your server IP and test domain)
::
@ -85,7 +88,11 @@ For example on your local computer (adjust your server IP and test domain)
Using nip.io (or other DNS wildcard services)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you cannot edit /etc/hosts or your DNS zone, don't give up yet, you can use services such as http://nip.io, http://xip.io, https://sslip.io/, or others.
If you cannot edit /etc/hosts or your DNS zone, don't give up yet, you can use services such as `nip.io`_, `xip.io`_, `sslip.io`_ or others.
.. _nip.io: http://nip.io/
.. _xip.io: http://xip.io/
.. _sslip.io: https://sslip.io
For example, if your server IP is 192.168.12.13, you can use 192-168-12-13.nip.io as your SSO domain:

View File

@ -334,13 +334,18 @@ Identity Provider
General parameters
^^^^^^^^^^^^^^^^^^
* **Want Authentication Request Signed**: set to On to require that received authentication request are signed.
* **Want Authentication Request Signed**: By default, LemonLDAP::NG requires all SAML Requests to be signed. Set it to "Off" to let each Service Provider metadata decide if their requests should be verified by LemonLDAP::NG or not.
.. tip::
This option can then be overridden for each Service
Provider.
The per-SP "Check SSO message signature" setting allows you to disable
signature verification even if this option is set to "On" globally
This option will set the `WantAuthnRequestsSigned` attribute to `true` in LemonLDAP::NG's IDP Metadata.
.. warning::
This setting requires Lasso 2.6.1 to be effective. Older versions behave as if this setting was set to "Off"
Single Sign On
^^^^^^^^^^^^^^

View File

@ -321,21 +321,19 @@ Go in Manager, ``General parameters`` » ``Advanced parameters`` »
- **Use Safe jail**: set to 'Off' to disable Safe jail. Safe module is
used to eval expressions in headers, rules, etc. Disabling it can
lead to security issues.
- **Avoid assignment in expressions**: Set to 'Off' to disable syntax checking.
Equal sign can be replaced by \x3D i.e. "dc\x3Dorg"
- **Check XSS Attacks**: Set to 'Off' to disable XSS checks. XSS checks
will still be done with warning in logs, but this will not prevent
the process to continue.
- **Brute-Force Attack protection**: set to 'On' to enable it. The aim
of a brute force attack is to gain access to user accounts by
repeatedly trying to guess the password of a user. If it is disabled,
automated tools may submit thousands of password attempts in a matter
of seconds, making it easy for an attacker to beat a password-based
authentication system.
- **Required token for forms**: To prevent CSRF attack, a token is
build for each form. To disable it, set this parameter to 'Off' or
set a special rule
- **Form timeout**: Form token timeout (default to 120 seconds)
- **Use global storage**: Local cache is used by default for one time
tokens. To use global storage, set it to 'On'
- **CrowdSec Bouncer**: set to 'On' to enable :doc:`CrowdSec Bouncer plugin<crowdsec>`
- **Brute-Force Attack protection**: set to 'On' to enable :doc:`Brute-force protection plugin<bruteforceprotection>`
- **LWP::UserAgent and SSL options**: insert here options to pass to
LWP::UserAgent object (used by SAML or OpenID-Connect to query
partners and AuthSSL or AuthBasic handler to request Portal URL).

View File

@ -4,11 +4,27 @@ SELinux
To make LemonLDAP::NG work with SELinux, you may need to set up some
options.
SELinux policy package
----------------------
If you are using a RPM distribution and Apache as the web server, you need to
install the ``lemonldap-ng-selinux`` package to configure SELinux context correctly ::
yum install lemonldap-ng-selinux
.. note::
On CentOS 8 and Fedora, this is done automatically
This package will not configure SELinux booleans, please read the next sections to see which booleans you need to enable manually
Disk cache (sessions an configuration)
--------------------------------------
You need to set the correct context on the cache directory
.. deprecated:: 2.0.10
this is now done by the ``lemonldap-ng-selinux`` package
::
semanage fcontext --add -t httpd_cache_t -f a '/var/cache/lemonldap-ng(/.*)?'

View File

@ -68,6 +68,12 @@ To configure sessions, go in Manager, ``General Parameters`` »
Command-line tools
==================
.. versionadded:: 2.0.9
You can use the ``lemonldap-ng-sessions`` tool to search, update or delete sessions. See a few examples in :ref:`the examples page <cli-sessions>`
.. deprecated:: 2.0.10
- LLNG Portal provides a simple tool to delete a session:
``llngDeleteSession``. To use it, simply give it the user identifier
*(wildcard are authorizated)*:

View File

@ -38,8 +38,8 @@ To edit SSO cookie parameters, go in Manager, ``General Parameters`` >
expiration time and use a session cookie.
- **Cookie SameSite value**: the value of the SameSite cookie attribute. By
default, LemonLDAP::NG will set it to "Lax" in most cases, and "None" if you
use SAML. Using "None" requres Secured Cookies, and accessing applications
over HTTPS on most web browsers.
use federated authentiication like SAML or OIdC. Using "None" requires Secured Cookies,
and accessing applications over HTTPS on most web browsers.
.. danger::

View File

@ -1,6 +1,10 @@
Documentation for LemonLDAP::NG 3.0
===================================
.. toctree::
Documentation index<documentation>
.. toctree::
:caption: Getting started
:hidden:
@ -152,13 +156,13 @@ Official Backends Authenticat
:doc:`Custom modules<authcustom>` |new| ✔ ✔ ✔
==================================================================== =============================================== ======== ========
==================================================================== ================================================= ======== ========
==================================================================== ================================================= ======== =========================
Combo Backends Authentication Users Password
==================================================================== ================================================= ======== ========
==================================================================== ================================================= ======== =========================
:doc:`Choice by users<authchoice>` ✔ ✔ ✔
:doc:`Combination of auth schemes<authcombination>` |new| ✔ ✔
:doc:`Combination of auth schemes<authcombination>` |new| ✔ ✔ ✔ (since *2.0.10*)
:doc:`Multiple backends stack<authmulti>` |deprecated| *Replaced by* :doc:`Combination<authcombination>`
==================================================================== ================================================= ======== ========
==================================================================== ================================================= ======== =========================
==================================================================== =============================================== ======== ========
Obsolete Backends Authentication Users Password
@ -267,23 +271,26 @@ Name Description
:doc:`Auto Signin<autosignin>` |new| Auto Signin Addon
:doc:`Brute Force protection<bruteforceprotection>` |new| User must wait to log in after some failed login attempts
:doc:`CDA<cda>` Cross Domain Authentication
:doc:`Check DevOps<checkdevops>` [5]_ |new| Check DevOps handler file plugin
:doc:`Check state<checkstate>` |new| Check state plugin (test page)
:doc:`Check user<checkuser>` [5]_ |new| Check access rights, transmitted headers and session attibutes for a specific user and URL
:doc:`Check user<checkuser>` [6]_ |new| Check access rights, transmitted headers and session attibutes for a specific user and URL
:doc:`Configuration viewer<viewer>` |new| Edit WebSSO configuration in Read Only mode
:doc:`Context switching<contextswitching>` [6]_\ |new| Switch context other users
:doc:`Context switching<contextswitching>` [7]_\ |new| Switch context other users
:doc:`CrowdSec<crowdsec>` [8]_\ |new| CrowdSec bouncer
:doc:`Custom<plugincustom>` Write a custom plugin
:doc:`Decrypt value<decryptvalue>` [7]_\ |image35| Decrypt ciphered values
:doc:`Display login history<loginhistory>`
:doc:`Decrypt value<decryptvalue>` [9]_\ |beta| Decrypt ciphered values
:doc:`Display login history<loginhistory>` Display Success/Fails logins
:doc:`Force Authentication<forcereauthn>` Force authentication to access to Portal
:doc:`Global Logout<globallogout>` [8]_ Suggest to close all opened sessions at logout
:doc:`Global Logout<globallogout>` [10]_ Suggest to close all opened sessions at logout
:doc:`Grant Sessions<grantsession>` Rules to apply before allowing a user to open a session
:doc:`Impersonation<impersonation>` [9]_\ |new| Allow users to use another identity
:doc:`Notifications system<notifications>`
:doc:`Impersonation<impersonation>` [11]_\ |new| Allow users to use another identity
:doc:`Find user<finduser>` [12]_\ |beta| Search for user account
:doc:`Notifications system<notifications>` DIsplay a message during log in process
:doc:`Portal Status<status>` Experimental portal status page
:doc:`Public pages<public_pages>` Enable public pages system
:doc:`Refresh session API<refreshsessionapi>` [10]_ Plugin that provides an API to refresh a user session
:doc:`Reset password by mail<resetpassword>`
:doc:`Reset certificate by mail<resetcertificate>` [11]_\ |image37| Allow users to reset their certificate
:doc:`Refresh session API<refreshsessionapi>` [13]_ Plugin that provides an API to refresh a user session
:doc:`Reset password by mail<resetpassword>` Send a mail to reset its password
:doc:`Reset certificate by mail<resetcertificate>` [14]_\ |beta| Allow users to reset their certificate
:doc:`REST services<restservices>` |new| REST server for :doc:`Proxy<authproxy>`
:doc:`SOAP services<soapservices>` |deprecated| SOAP server for :doc:`Proxy<authproxy>`
:doc:`Stay connected<stayconnected>` |new| Enable persistent connection on same browser
@ -301,12 +308,12 @@ Handlers are software control agents to be installed on your web servers
==================================================================== ========== ============================================================= =========================================== ================================================================================== =============================================== ======================================================================================================================
Handler type Apache LLNG FastCGI/uWSGI server (Nginx, or :doc:`SSOaaS<ssoaas>`) `Plack servers <https://plackperl.org>`__ Node.js ( `express apps <http://expressjs.com/>`__\ or :doc:`SSOaaS<ssoaas>`) :doc:`Self protected apps<selfmadeapplication>` Comment
==================================================================== ========== ============================================================= =========================================== ================================================================================== =============================================== ======================================================================================================================
Main *(default handler)* ✔ ✔ ✔ :doc:`Partial<nodehandler>` ** [12]_ **
Main *(default handler)* ✔ ✔ ✔ :doc:`Partial<nodehandler>` ** [15]_ **
:doc:`AuthBasic<handlerauthbasic>` ✔ ✔ ✔ ✔ Designed for some server-to-server applications
:doc:`CDA<cda>` ✔ ✔ ✔ ✔ For Cross Domain Authentication
:doc:`DevOps<devopshandler>` (:doc:`SSOaaS<ssoaas>`) |new| ✔ ✔ ✔ ✔ Allows application developers to define their own rules and headers inside their applications
:doc:`DevOpsST<devopssthandler>` (:doc:`SSOaaS<ssoaas>`) |new| ✔ ✔ ✔ ✔ Enables both :doc:`DevOps<devopshandler>` and :doc:`Service Token<servertoserver>`
:doc:`OAuth2<oauth2handler>` [13]_\ |new| ✔ ✔ ✔ ✔ Uses OpenID Connect/OAuth2 access token to check authentication and authorization, can be used to protect Web Services
:doc:`OAuth2<oauth2handler>` [16]_\ |new| ✔ ✔ ✔ ✔ Uses OpenID Connect/OAuth2 access token to check authentication and authorization, can be used to protect Web Services
:doc:`Secure Token<securetoken>` ✔ ✔ ✔ Designed to secure exchanges between a LLNG reverse-proxy and a remote app
:doc:`Service Token<servertoserver>` |new| *(Server-to-Server)* ✔ ✔ ✔ ✔ ✔ Designed to permit underlying requests *(API-Based Infrastructure)*
:doc:`Zimbra PreAuth<applications/zimbra>` ✔ ✔ ✔
@ -379,16 +386,16 @@ style modules are usable except for some features.
Backend Shareable :ref:`Session explorer<session-explorer>` :ref:`Session restrictions<session-restrictions>` Session expiration Comment
================================================================ ========= ================================================ ==================================================== ================== =================================================================================================================================================================================================
:doc:`File<filesessionbackend>` ✔ ✔ ✔ Not shareable between servers except if used in conjunction with :doc:`REST session backend<restsessionbackend>` or with a shared file system (NFS,...). Selected by default during installation.
:doc:`SQL<sqlsessionbackend>` ✔ ✔ ✔ ✔ Unoptimized for :doc:`session explorer<features>` and :doc:`single session<features>` features.
:doc:`LDAP<ldapsessionbackend>` ✔ ✔ ✔ ✔
:doc:`PgJSON<pgjsonsessionbackend>` ✔ ✔ ✔ ✔ Recommended backend for production installations
:doc:`Browseable MySQL<browseablemysqlsessionbackend>` ✔ ✔ ✔ ✔ Recommended for those who prefer MySQL
:doc:`Browseable LDAP<browseableldapsessionbackend>` ✔ ✔ ✔ ✔
:doc:`Redis<nosqlsessionbackend>` ✔ ✔ ✔ ✔ The fastest. Must be secured by network access control.
:doc:`MongoDB<mongodbsessionbackend>` ✔ ✔ ✔ ✔ Must be secured by network access control.
:doc:`Browseable (SQL, Redis or LDAP)<browseablesessionbackend>` ✔ ✔ ✔ ✔ **Optimized** for :doc:`session explorer<features>` and :doc:`single session<features>` features.
:doc:`SQL<sqlsessionbackend>` ✔ ✔ ✔ ✔ Unoptimized for :doc:`session explorer<features>` and :doc:`single session<features>` features.
:doc:`REST<restsessionbackend>` |new| ✔ ✔ ✔ ✔ Proxy backend to be used in conjunction with another session backend.
:doc:`SOAP<soapsessionbackend>` |deprecated| ✔ ✔ ✔ ✔ Proxy backend to be used in conjunction with another session backend.
================================================================ ========= ================================================ ==================================================== ================== =================================================================================================================================================================================================
.. tip::
You can migrate from one session backend to another using the
@ -557,41 +564,52 @@ by your language code):
:doc:`Radius second factor<radius2f>` is available with LLNG ≥ 2.0.6
.. [4]
:doc:`Check DevOps file plugin<checkdevops>` are available with LLNG ≥
2.0.12
.. [5]
:doc:`Additional second factors<sfextra>` are available with LLNG ≥
2.0.6
.. [5]
.. [6]
:doc:`Check user plugin<checkuser>` is available with LLNG ≥ 2.0.3
.. [6]
.. [7]
:doc:`Context switching plugin<contextswitching>` is available with
LLNG ≥ 2.0.6
.. [7]
.. [8]
:doc:`CrowdSec bouncer <crowdsec>` is available with LLNG ≥ 2.0.12
.. [9]
:doc:`Decrypt value plugin<decryptvalue>` is available with LLNG ≥
2.0.7
.. [8]
.. [10]
:doc:`Global Logout plugin<globallogout>` is available with LLNG ≥
2.0.7
.. [9]
.. [11]
:doc:`Impersonation plugin<impersonation>` is available with LLNG ≥
2.0.3
.. [10]
.. [12]
:doc:`Find user plugin<finduser>` is available with LLNG ≥
2.0.11
.. [13]
:doc:`Refresh session API plugin<refreshsessionapi>` is available
with LLNG ≥ 2.0.7
.. [11]
.. [14]
:doc:`Reset certificate by mail plugin<resetcertificate>` is
available with LLNG ≥ 2.0.7
.. [12]
.. [15]
:doc:`Node.js handler<nodehandler>` has not yet reached the same
level of functionalities
.. [13]
.. [16]
:doc:`OAuth2 Handler<oauth2handler>` is available with LLNG ≥ 2.0.4
.. |image0| image:: /icons/kthememgr.png
@ -603,10 +621,6 @@ by your language code):
.. |image26| image:: /icons/personal.png
.. |image27| image:: /icons/neotux.png
.. |image28| image:: /icons/personal.png
.. |image35| image:: /documentation/beta.png
:width: 35px
.. |image37| image:: /documentation/beta.png
:width: 35px
.. |image41| image:: /icons/gpg.png
.. |image46| image:: /icons/utilities.png
.. |image50| image:: /icons/kmultiple.png
@ -615,6 +629,10 @@ by your language code):
.. |image57| image:: /icons/jabber_protocol.png
.. |image59| image:: /icons/xeyes.png
.. |beta| image:: /documentation/beta.png
:width: 35px
:alt: beta
.. |new| image:: /documentation/new.png
:alt: new

View File

@ -0,0 +1,132 @@
Test OpenID Connect with command line tools
===========================================
We present here how to test the OpenID Connect protocol (authorization code flow) with commande line tools, like `curl`.
We use in this example a public OIDC provider based on LL::NG: `<https://oidctest.wsweet.org>`_
Authentication
--------------
The first step is to obtain a valid SSO session on the portal. Several solutions:
* Use a web browser and log into the portal, then get the value of the SSO cookie
* Use portal REST API, and adapt the `requireToken` configuration to get cookie value in JSON response (see :doc:`REST services<restservices>`)
Example of REST service usage, with credentials `dwho`/`dwho`:
.. code-block:: shell
curl -X POST -d user=dwho -d password=dwho -H 'Accept: application/json' 'https://oidctest.wsweet.org/oauth2/'
The session id is displayed in JSON response:
.. code-block:: javascript
{
"error" : "0",
"id" : "0640f95827111f00ba7ad5863ba819fe46cfbcecdb18ce525836369fb4c8350b",
"result" : 1
}
Authorization code
------------------
In the first step of authorization code flow, we request a temporary code, ont the `authorize` end point.
Parameters needed:
* SSO session id (will be passed in `lemonldap` cookie, adapt the name if needed)
* Client ID: given by your OIDC provider, we use here `private`
* Scope: depends on which information you need, we will use here `openid profile email`
* Redirect URI: shoud match the value registered in your OIDC provider, we will use here `http://localhost`
The OIDC provide will return the code in the location header, so we just output this reponse header:
.. code-block:: shell
curl -s -D - -o /dev/null -b lemonldap=0640f95827111f00ba7ad5863ba819fe46cfbcecdb18ce525836369fb4c8350b 'https://oidctest.wsweet.org/oauth2/authorize?response_type=code&client_id=private&scope=openid+profile+email&redirect_uri=http://localhost' | grep '^location'
The value of the location header is:
.. code-block:: shell
location: http://localhost?code=294b0facd91a0fa92762edc48d18369e99c330ba2b8fb05ab2c45999fcef6e17&session_state=BpB8KRMBEDUs%2B7lAjsz4DRk3E0RJImxgUbMsCFFAUa8%3D.N3dVOFg3a2RpNXVJK3ltSldrYXZjUjhtU0tvd29sWkpuWWJJbll5ZGs5NzhZMnh5bmQwd0IxRmJVWUxJSTlkWDBnSWZ2SWFVZmU0UnRaMkVJVjNUY3c9PQ
So we get the code value: `94b0facd91a0fa92762edc48d18369e99c330ba2b8fb05ab2c45999fcef6e17`
This code has a short lifetime, we will use it to get access token and ID token in the next step
Tokens
------
In this step, we exchange the authorization code against tokens:
* Access token
* ID token
* Refresh token (optional)
Parameters needed:
* Authorization code: see previous step
* Grant type: we use here `authorization_code`
* Redirect URI: same value as the one used in the previous step
* Client ID and Client Secret: given by your OIDC provider, we use here `private`/`tardis`
.. code-block:: shell
curl -X POST -d grant_type=authorization_code -d 'redirect_uri=http://localhost' -d code=94b0facd91a0fa92762edc48d18369e99c330ba2b8fb05ab2c45999fcef6e17 -u 'private:tardis' 'https://oidctest.wsweet.org/oauth2/token' | json_pp
The JSON response looks like this:
.. code-block:: javascript
{
"access_token" : "a88b8dde538719e55c3cb8fbd14d06ed77853c685a62abf6ecb88d86228a9c64",
"expires_in" : 3600,
"id_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6Im9pZGN0ZXN0IiwidHlwIjoiSldUIn0.eyJhdXRoX3RpbWUiOjE2MTQxNjAwMDYsImlhdCI6MTYxNDE2MzIxOCwiaXNzIjoiaHR0cHM6Ly9vaWRjdGVzdC53c3dlZXQub3JnLyIsImF0X2hhc2giOiJIVGswOVNjSjRObEFua3k5SGFFX2VRIiwiYWNyIjoibG9hLTIiLCJleHAiOjE2MTQxNjY4MTgsInN1YiI6ImR3aG8iLCJhenAiOiJwcml2YXRlIiwiYXVkIjpbInByaXZhdGUiXX0.N3TNufjKLzKM3qiIitA7JHUei4L572XjF6AcVl7UAFB6efdGUCiAL7amlUl0FgjZfzW9bzvulBVDidoYSicIaysIdI4KkjmjpVN0Z3gOSu0ecuk5p8fD1KbX6-tmA3txeR18nzfhdckq-S-6Lx7wrWpPNyrzGx-FImbOaUPN2yeVhKPXhdyHJbzI0RqJETxnBkyW-CLEzAJyq3rCUVX-D8kHADvg6a42QQyPdxvBuGrdBfyDDDb_Py13H1qhn40NnuFknR1wSahsY6U97uUooyk-0_U4J3XJAHySjCtivtSeP0fM_5eblMuh6WdVjrfnUF0xnCTbCa2gYRlTS38BkqcsWY26PXoRAOo31a1cmB5sMSZyPtRF9UZcmGiNBIymMMdFgVAJONb6uliiTS5j9-nkmHOqVC-XJ6tuiU3ZSBQ8nCRyNW2LaCzpJ5c3ytP9yYQtyT8HmhN0VnXob3K1uJEA_Xcu4sADjtrm-LbrGiwaVMkfu-C6YIrbuC9riOW6TneV2gAzAjXPOW_UZeXrCrx66GHIJPsJIq29UfbTN5Pxo9SH2yKw6PSfxevkZhBIhEXCOMaIUHrlWz2jDBBzPIWeiSRbK_MRtejQmdRUs8nqdq-McVwnFiUMDt1KZXxqScTtMDF_Lo9oK2RaCijEJ7MSPEscr_YOyp3KIq2FLVg",
"refresh_token" : "19434440ed4da2803e8ba9d91cb2eabd5b8bd12af2609429bda03ed487e6ef57",
"token_type" : "Bearer"
}
The access token will be used for the last step, to get information about the user.
The ID Token is a JWT (JSON Web Token) and can be parsed easily, as this is the concatenation of 3 JSON strings encoded in base 64: `base64(header).base64(payload).base64(signature)`.
Decoding the payload gives:
.. code-block:: javascript
{
"acr" : "loa-2",
"at_hash" : "HTk09ScJ4NlAnky9HaE_eQ",
"aud" : [
"private"
],
"auth_time" : 1614160006,
"azp" : "private",
"exp" : 1614166818,
"iat" : 1614163218,
"iss" : "https://oidctest.wsweet.org/",
"sub" : "dwho"
}
User info
---------
This step is optional and allows to fetch user information linked to scopes requested in the first step.
Parameters needed:
* Access token, used as bearer authorization
.. code-block:: shell
curl -H 'Authorization: Bearer a88b8dde538719e55c3cb8fbd14d06ed77853c685a62abf6ecb88d86228a9c64' 'https://oidctest.wsweet.org/oauth2/userinfo' | json_pp
JSON response:
.. code-block:: javascript
{
"email" : "dwho@badwolf.org",
"name" : "Doctor Who",
"preferred_username" : "dwho",
"sub" : "dwho"
}

View File

@ -1,28 +1,148 @@
Upgrade from 2.0.x to 2.0.y
===========================
Please apply general caution as you would with any software: have
backups and a rollback plan ready!
Known issues
-------------
.. danger::
Upgrading from 2.0.0 or 2.0.1 to later versions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you have
:doc:`installed LemonLDAP::NG from official RPMs<installrpm>`, you may
run into bug
`#1757 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1757>`__
and lose your Apache configuration files while updating from
LemonLDAP::NG 2.0.0 or 2.0.1 to later versions. Please backup your
``/etc/httpd/conf.d/z-lemonldap-ng-*.conf`` files before the
update.
If you have :doc:`installed LemonLDAP::NG from official RPMs<installrpm>`, you
may run into bug `#1757
<https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues/1757>`__ and lose your
Apache configuration files while updating from LemonLDAP::NG 2.0.0 or 2.0.1 to
later versions. Please backup your ``/etc/httpd/conf.d/z-lemonldap-ng-*.conf``
files before the update.
.. Adjust for every new version that has known, unreleased bugs
Known regressions in the latest released version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
None
2.0.12
------
Client Credential sessions missing expiration time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you started using Client Credential grants in 2.0.11, you may have encountered
`issue 2481 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2481>`__.
Because of this bug, the created sessions may never be purged by the `purgeCentralCache` script.
In order to detect these sessions, you can run the following command:
::
lemonldap-ng-sessions search --where _session_kind=SSO --select _session_id --select _utime | \
jq -r '. | map(select(._utime == null)) | map(._session_id) | join ("\n")'
This will output a list of SSO sessions with no expiration time.
Review them manually using ::
lemonldap-ng-sessions get <session_id>
You can then remove them with ::
lemonldap-ng-sessions delete <session_id> <session_id> <etc.>
2.0.11
------
Portal templates changes
~~~~~~~~~~~~~~~~~~~~~~~~
If you created your own skin and modified some template files, you may need to update them.
No change is required if you are using the default ``bootstrap`` theme.
A new plugin has been introduced, in beta version: :doc:`FindUser <finduser>`. It requires a modification of ``login.tpl`` to include ``finduser.tpl``.
2.0.10
------
Security
~~~~~~~~
A vulnerability affecting LemonLDAP::NG installations has been found out when ALL following criteria apply:
* Your handler server uses Nginx
* Your virtual host configuration contains per-URL ``skip`` or ``unprotect`` access rule
In this situation, you have to update your LUA configuration file like ``/etc/nginx/nginx-lua-headers.conf``. See also `issue 2434 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2434>`__.
Other minor security fixes:
* It is now possible to hide sessions identifier in Manager (parameter ``displaySessionId``). See also `issue 2350 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2350>`__.
* Second factor management by end user now requires safer conditions. See also `issue 2332 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2332>`__, `issue 2337 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2337>`__ and `issue 2338 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2338>`__.
Main changes
~~~~~~~~~~~~
- New dependency: IO::Socket::Timeout
- TOTP check tolerates forward AND backward clock drift (totp2fRange)
- Avoid assignment in expressions option is disabled by default
- RHEL/CentOS SELinux users should install the new ``lemonldap-ng-selinux`` package to fix `an issue with the new default cache directory <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2401>`__
- If you use :doc:`applications/mattermost` with OpenID Connect, you need to set the ``id`` claim type to *Integer*
- BruteForceProtection plugin now prevents authentication on backend if an account is locked
- In the Manager API, postLogoutRedirectUri is now `returned and consumed as an array <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2347>`__
- We fixed a bug that caused SAML sessions to be created and never deleted, you should check your session databases for sessions that have ``"_session_kind": "ISAML"`` but no ``_utime``. You can safely delete SAML sessions with no ``_utime`` during the upgrade.
Portal templates changes
~~~~~~~~~~~~~~~~~~~~~~~~
If you created your own skin and modified some template files, you may need to update them, see below if they have been modified.
No change is required if you are using the default ``bootstrap`` theme.
2FA manager
^^^^^^^^^^^
In ``2fregisters.tpl`` you need to add the ``remove2f`` class to the button that triggers second factor removal:
.. code-block:: diff
- <span device='<TMPL_VAR NAME="type">' epoch='<TMPL_VAR NAME="epoch">' class="btn btn-danger" role="button">
+ <span device='<TMPL_VAR NAME="type">' epoch='<TMPL_VAR NAME="epoch">' class="btn btn-danger remove2f" role="button">
Or, better yet, integrate the changes in ``2fregisters.tpl`` and ``skin.min.js`` into your custom theme to benefit from the `new 2F removal confirmation dialog <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2438>`__
Checkboxes
^^^^^^^^^^
A CSS change has been done in ``styles.css`` to avoid checkbox labels overflow. See `issue 2301 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2301>`__.
The ``form-check-input`` class is missing in ``register.tpl`` and ``notifinclude.tpl``. See `issue 2374 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2374>`__.
Password checker
^^^^^^^^^^^^^^^^
Input id values have been modified in ``mail.tpl`` to work with password checker. See `issue 2355 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2355>`__.
Tables caption
^^^^^^^^^^^^^^
Tables captions have been added in ``sessionArray.tpl``. See `issue 2356 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2356>`__.
Stay connected
^^^^^^^^^^^^^^
A small change is required in ``checklogins.tpl`` for `issue 2365 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2365>`__.
Other changes needed in ``2fchoice.tpl``, ``ext2check.tpl``, ``totp2fcheck.tpl``, ``u2fcheck.tpl`` and ``utotp2fcheck.tpl`` for `issue 2366 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2366>`__.
Mails
^^^^^
The HTML ``alt`` attribute has been added on ``img`` in all ``mail_*.tpl``. See `issue 2422 <https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/-/issues/2422>`__.
2.0.9
-----
@ -34,6 +154,7 @@ backups and a rollback plan ready!
- SAML SOAP calls are now using ``text/xml`` instead of ``application/xml`` as the MIME Content Type, as required by `the SOAP standard <https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383526>`__
- Incremental lock times values can now be set in BruteForceProtection plugin through Manager.
It MUST be a list of comma separated values. Default values are ``5, 15, 60, 300, 600``
- This version is not compatible with :doc:`applications/mattermost`
Cookie issues with Chrome
~~~~~~~~~~~~~~~~~~~~~~~~~
@ -58,6 +179,10 @@ your existing ``localSessionStorageOptions/cache_root`` parameter from ``/tmp``
to ``/var/cache/lemonldap-ng``. Be sure to create this directory on your
file system before modifying your configuration.
If you are using SELinux, you also need to run the following commands ::
semanage fcontext --add -t httpd_cache_t -f a '/var/cache/lemonldap-ng(/.*)?'
restorecon -R /var/cache/lemonldap-ng/
Required changes in NGINX handler rules (CVE-2020-24660)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1,7 +1,7 @@
Writing rules and headers
=========================
Lemonldap::NG manage applications by their hostname (Apache's
Lemonldap::NG manages applications by their hostname (Apache's
virtualHosts). Rules are used to protect applications, headers are HTTP
headers added to the request to give datas to the application (for logs,
profiles,...).

View File

@ -4,7 +4,7 @@ info:
description: The Manager API allows an administrator to modify the LemonLDAP::NG configuration programmatically. It is not meant to be accessed by end users. The client libraries mentionned in examples can be generated from doc/sources/manager-api/openapi-spec.yaml
version: 2.0.9
servers:
- url: /api/v1
- url: https://manager-api.example.com
tags:
- name: samlsp
description: SAML Service Providers
@ -1188,6 +1188,10 @@ components:
myMacroName: "$macro(rule)"
options:
$ref: '#/components/schemas/OidcOptions'
scopeRules:
type: object
example:
write: "requested and inGroup('writers')"
OidcOptions:
type: object
properties:
@ -1201,6 +1205,18 @@ components:
type: string
allowOffline:
type: boolean
accessTokenSignAlg:
type: string
enum:
- none
- RS256
- RS384
- RS512
default: HS512
accessTokenJWT:
type: bool
accessTokenClaims:
type: bool
authnLevel:
type: integer
rule:
@ -1221,7 +1237,9 @@ components:
public:
type: boolean
postLogoutRedirectUris:
type: string
type: array
items:
type: string
logoutType:
type: string
enum:
@ -1232,6 +1250,10 @@ components:
type: integer
IDTokenForceClaims:
type: boolean
additionalAudiences:
type: array
items:
type: string
requirePKCE:
type: boolean
offlineSessionExpiration:
@ -1275,6 +1297,10 @@ components:
myMacroName: "$macro(rule)"
options:
$ref: '#/components/schemas/OidcOptions'
scopeRules:
type: object
example:
write: "requested and inGroup('writers')"
OidcRpReplace:
type: object
required:
@ -1299,6 +1325,10 @@ components:
myMacroName: "$macro(rule)"
options:
$ref: '#/components/schemas/OidcOptions'
scopeRules:
type: object
example:
write: "requested and inGroup('writers')"
CasApp:
required:

View File

@ -19,7 +19,7 @@ dirName=__pwd__/e2e-tests/conf
[portal]
checkXSS = 0
checkXSS = 1
portalSkin = bootstrap
staticPrefix = /static
languages = fr, en, vi, it, ar, de, zh, nl, es, pt, ro, tr, zh_TW

View File

@ -1,4 +1,4 @@
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================

View File

@ -39,6 +39,7 @@ lib/Lemonldap/NG/Common/EmailTransport.pm
lib/Lemonldap/NG/Common/FormEncode.pm
lib/Lemonldap/NG/Common/IO/Filter.pm
lib/Lemonldap/NG/Common/IPv6.pm
lib/Lemonldap/NG/Common/JWT.pm
lib/Lemonldap/NG/Common/Logger/_Duplicate.pm
lib/Lemonldap/NG/Common/Logger/Apache2.pm
lib/Lemonldap/NG/Common/Logger/Dispatch.pm

View File

@ -4,7 +4,7 @@
"Xavier Guimard <x.guimard@free.fr>, Clément Oudot <clement@oodo.net>"
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010",
"generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010",
"license" : [
"open_source"
],
@ -57,6 +57,7 @@
"Digest::SHA" : "0",
"HTML::Template" : "0",
"JSON" : "0",
"JSON::XS" : "0",
"Mouse" : "0",
"Plack" : "0",
"Test::Pod" : "1",
@ -77,5 +78,5 @@
"x_MailingList" : "mailto:lemonldap-ng-dev@ow2.org"
},
"version" : "v2.1.0",
"x_serialization_backend" : "JSON::PP version 4.02"
"x_serialization_backend" : "JSON::PP version 4.04"
}

View File

@ -10,7 +10,7 @@ build_requires:
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010'
generated_by: 'ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010'
license: open_source
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@ -42,6 +42,7 @@ requires:
Digest::SHA: '0'
HTML::Template: '0'
JSON: '0'
JSON::XS: '0'
Mouse: '0'
Plack: '0'
Test::Pod: '1'

View File

@ -79,6 +79,7 @@ WriteMakefile(
'Digest::SHA' => 0,
'HTML::Template' => 0,
'JSON' => 0,
'JSON::XS' => 0,
'Mouse' => 0,
'Plack' => 0,
'Test::Pod' => 1.00,

View File

@ -1,6 +1,8 @@
package Lemonldap::NG::Common::Apache::Session::Store;
use strict;
our $VERSION = '2.1.0';
sub new {

View File

@ -74,7 +74,7 @@ sub _search {
$selectField, $value, @fields );
}
else {
die "Invalid --where option" . $self->opts->{where};
die "Invalid --where option : " . $self->opts->{where};
}
}
else {
@ -166,9 +166,19 @@ sub _get_one_data {
sub delete {
my ($self) = shift;
my $result = 0;
my @sessions;
# Run search if a where option was provided
if ( $self->opts->{where} ) {
my $res = $self->_search();
@sessions = keys %{$res};
}
else {
@sessions = @_;
}
my @result;
for my $id (@_) {
for my $id (@sessions) {
my $as = $self->_get_one_session($id);
if ($as) {
unless ( $as->remove ) {

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Common::Conf::AccessLib;
use 5.10.0;
use strict;
use utf8;
use Mouse;

View File

@ -29,8 +29,9 @@ use constant DEFAULTCONFBACKEND => "File";
use constant DEFAULTCONFBACKENDOPTIONS => (
dirName => '/usr/local/lemonldap-ng/data/conf',
);
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)s)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:State|User|XSS)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|wsdlServer)$/;
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|ScopeRule|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)s)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $arrayParameters = qr/^mySessionAuthorizedRWKeys$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:DevOps(?:Download)?|State|User|XSS)|rowdsec|da)|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|(?:wsdlServ|findUs)er)$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
@ -57,6 +58,7 @@ our %EXPORT_TAGS = (
DEFAULTCONFBACKENDOPTIONS
NO
$hashParameters
$arrayParameters
@sessionTypes
$boolKeys
)

View File

@ -19,7 +19,7 @@ sub defaultValues {
'authentication' => 'Demo',
'available2F' => 'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,Yubikey,Radius',
'available2FSelfRegistration' => 'TOTP,U2F,Yubikey',
'bruteForceProtectionLockTimes' => '5, 15, 60, 300, 600',
'bruteForceProtectionLockTimes' => '15, 30, 60, 300, 600',
'bruteForceProtectionMaxAge' => 300,
'bruteForceProtectionMaxFailed' => 3,
'bruteForceProtectionMaxLockTime' => 900,
@ -35,10 +35,12 @@ sub defaultValues {
'certificateResetByMailURL' =>
'http://auth.example.com/certificateReset',
'certificateResetByMailValidityDelay' => 0,
'checkDevOpsDownload' => 1,
'checkTime' => 600,
'checkUserDisplayComputedSession' => 1,
'checkUserDisplayEmptyHeaders' => 0,
'checkUserDisplayEmptyValues' => 0,
'checkUserDisplayNormalizedHeaders' => 0,
'checkUserDisplayPersistentInfo' => 0,
'checkUserHiddenAttributes' => '_loginHistory _session_id hGroups',
'checkUserIdRule' => 1,
@ -56,6 +58,7 @@ sub defaultValues {
'corsEnabled' => 1,
'corsExpose_Headers' => '*',
'corsMax_Age' => '86400',
'crowdsecAction' => 'reject',
'cspConnect' => '\'self\'',
'cspDefault' => '\'self\'',
'cspFont' => '\'self\'',
@ -84,6 +87,8 @@ sub defaultValues {
'facebookUserField' => 'id',
'failedLoginNumber' => 5,
'favAppsMaxNumber' => 3,
'findUserControl' => '^[*\\w]+$',
'findUserWildcard' => '*',
'formTimeout' => 120,
'githubAuthnLevel' => 1,
'githubScope' => 'user:email',

View File

@ -418,7 +418,7 @@ sub _oidcMetaDataNodes {
}
# Return all exported attributes if asked
elsif ( $query =~
/^(?:oidc${type}MetaDataExportedVars|oidcRPMetaDataOptionsExtraClaims|oidcRPMetaDataMacros)$/
/^(?:oidc${type}MetaDataExportedVars|oidcRPMetaDataOptionsExtraClaims|oidcRPMetaDataMacros|oidcRPMetaDataScopeRules)$/
)
{
my $pk = eval { $self->getConfKey( $req, $query )->{$partner} } // {};

View File

@ -22,12 +22,12 @@ our $specialNodeHash = {
};
our $doubleHashKeys = 'issuerDBGetParameters';
our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|(?:(?:d(?:emo|bi)|webID)E|e)xportedVar|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:(?:UserAttribut|Servic|Rul)e|AuthnLevel)|(?:ExportedVar|Macro)s)';
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:uth(?:orizationCodeExpiration|nLevel)|llow(?:PasswordGrant|Offline)|ccessTokenExpiration|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|(?:ExportedVar|Macro)s)';
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Expiration|SignAlg|Claims|JWT)|uth(?:orizationCodeExpiration|nLevel)|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|(?:ExportedVar|ScopeRule|Macro)s)';
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ign(?:S[LS]OMessage|atureMethod)|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:S(?:ign(?:S[LS]OMessage|atureMethod)|essionNotOnOrAfterTimeout)|N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|AuthnLevel|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)';
our $virtualHostKeys = '(?:vhost(?:A(?:ccessToTrace|uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
@ -36,7 +36,7 @@ our $authParameters = {
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],
apacheParams => [qw(apacheAuthnLevel)],
casParams => [qw(casAuthnLevel)],
choiceParams => [qw(authChoiceParam authChoiceModules authChoiceAuthBasic)],
choiceParams => [qw(authChoiceParam authChoiceModules authChoiceAuthBasic authChoiceFindUser)],
combinationParams => [qw(combination combModules combinationForms)],
customParams => [qw(customAuth customUserDB customPassword customRegister customResetCertByMail customAddParams)],
dbiParams => [qw(dbiAuthnLevel dbiExportedVars dbiAuthChain dbiAuthUser dbiAuthPassword dbiUserChain dbiUserUser dbiUserPassword dbiAuthTable dbiUserTable dbiAuthLoginCol dbiAuthPasswordCol dbiPasswordMailCol userPivot dbiAuthPasswordHash dbiDynamicHashEnabled dbiDynamicHashValidSchemes dbiDynamicHashValidSaltedSchemes dbiDynamicHashNewPasswordScheme)],
@ -45,7 +45,7 @@ our $authParameters = {
githubParams => [qw(githubAuthnLevel githubClientID githubClientSecret githubUserField githubScope)],
gpgParams => [qw(gpgAuthnLevel gpgDb)],
kerberosParams => [qw(krbAuthnLevel krbKeytab krbByJs krbRemoveDomain krbAllowedDomains)],
ldapParams => [qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapVerify ldapBase managerDn managerPassword ldapTimeout ldapIOTimeout ldapVersion ldapRaw ldapCAFile ldapCAPath AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapITDS)],
ldapParams => [qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapVerify ldapBase managerDn managerPassword ldapTimeout ldapIOTimeout ldapVersion ldapRaw ldapCAFile ldapCAPath AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapGetUserBeforePasswordChange ldapITDS)],
linkedinParams => [qw(linkedInAuthnLevel linkedInClientID linkedInClientSecret linkedInFields linkedInUserField linkedInScope)],
nullParams => [qw(nullAuthnLevel)],
oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],
@ -54,7 +54,7 @@ our $authParameters = {
proxyParams => [qw(proxyAuthnLevel proxyAuthService proxySessionService remoteCookieName proxyUseSoap)],
radiusParams => [qw(radiusAuthnLevel radiusSecret radiusServer)],
remoteParams => [qw(remotePortal remoteCookieName remoteGlobalStorage remoteGlobalStorageOptions)],
restParams => [qw(restAuthnLevel restAuthUrl restUserDBUrl restPwdConfirmUrl restPwdModifyUrl)],
restParams => [qw(restAuthnLevel restAuthUrl restUserDBUrl restPwdConfirmUrl restPwdModifyUrl restFindUserDBUrl)],
slaveParams => [qw(slaveAuthnLevel slaveUserHeader slaveMasterIP slaveHeaderName slaveHeaderContent slaveDisplayLogo slaveExportedVars)],
sslParams => [qw(SSLAuthnLevel SSLVar SSLVarIf sslByAjax sslHost)],
twitterParams => [qw(twitterAuthnLevel twitterKey twitterSecret twitterAppName twitterUserField)],

View File

@ -109,6 +109,21 @@ sub unserialize {
return $self->oldUnserialize($fields);
}
}
elsif ( $k =~ $arrayParameters ) {
unless ( utf8::is_utf8($v) ) {
$v = encode( 'UTF-8', $v );
}
$conf->{$k} = (
$v =~ /./
? eval { from_json( $v, { allow_nonref => 1 } ) }
: {}
);
if ($@) {
$Lemonldap::NG::Common::Conf::msg .=
"Unable to decode $k, switching to old format.\n";
return $self->oldUnserialize($fields);
}
}
else {
$conf->{$k} = $v;
}

View File

@ -1,5 +1,6 @@
package Lemonldap::NG::Common::EmailTransport;
use strict;
use Email::Sender::Transport::SMTP qw();
use MIME::Entity;
use Email::Sender::Simple qw(sendmail);

View File

@ -1,8 +1,10 @@
package Lemonldap::NG::Common::IPv6;
use strict;
use base 'Exporter';
@EXPORT = qw(&isIPv6 &net6 &expand6);
our $VERSION = '2.0.10';
our @EXPORT = qw(&isIPv6 &net6 &expand6);
sub isIPv6 {
my ($ip) = @_;
@ -15,7 +17,7 @@ sub net6 {
# Convert to binary
my $b = join '',
map { unpack( 'B*', pack( 'H*', $_ ) ) } split( ':', expand6($ip) );
$net = substr $b, 0, $bits;
my $net = substr $b, 0, $bits;
$net .= '0' x ( 128 - length($net) );
$net = unpack( 'H*', pack( 'B*', $net ) );
$net = join( ':', ( unpack "a4" x 8, $net ) );
@ -24,6 +26,7 @@ sub net6 {
}
sub expand6 {
my @arr;
my @_parts = ( $_[0] =~ /([0-9A-Fa-f]+)/g );
my $nparts = scalar @_parts;
if ( $nparts != 8 ) {

View File

@ -0,0 +1,86 @@
package Lemonldap::NG::Common::JWT;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK =
qw(getAccessTokenSessionId getJWTHeader getJWTPayload getJWTSignature getJWTSignedData)
; # symbols to export on request
use JSON;
use MIME::Base64 qw/encode_base64 decode_base64/;
# Gets the Access Token session ID embedded in a LLNG-emitted JWT
sub getAccessTokenSessionId {
my ($access_token) = @_;
# Access Token is a JWT, extract the JTI field
# and use it as session ID
if ( index( $access_token, '.' ) > 0 ) {
my $data = getJWTPayload($access_token);
if ( $data and $data->{jti} ) {
return $data->{jti};
}
else {
return;
}
}
# Access Token is the session ID directly
else {
return $access_token;
}
}
# Isolate and decode parts of a JWT
# @param jwt in serialized form
# @param part 0 for header, 1 for payload, 2 for signature
# @param json whether or not to decode as JSON
# @return JSON string
sub getJWTPart {
my ( $jwt, $part ) = @_;
my @jwt_parts = split( /\./, $jwt );
my $data = decode_base64url( $jwt_parts[$part] );
my $json_hash;
eval { $json_hash = from_json($data); };
return undef if ($@);
return $json_hash;
}
# Return the JWT data that has to be signed by the OP
# @param jwt serialized JWT
# @return the string data to pass to the signature method
sub getJWTSignedData {
my ($jwt) = @_;
my @jwt_parts = split( /\./, $jwt );
return ( $jwt_parts[0] . "." . $jwt_parts[1] );
}
# Convenience method to get the decoded JWT header
# @param jwt JWT in serialized form
# @return Perl hash
sub getJWTHeader {
my ($jwt) = @_;
return getJWTPart( $jwt, 0 );
}
# Convenience method to get the decoded JWT payload
# @param jwt JWT in serialized form
# @return Perl hash
sub getJWTPayload {
my ($jwt) = @_;
return getJWTPart( $jwt, 1 );
}
sub getJWTSignature {
my ($jwt) = @_;
my @jwt_parts = split( /\./, $jwt );
return $jwt_parts[2];
}
sub decode_base64url {
my $s = shift;
$s =~ tr[-_][+/];
$s .= '=' while length($s) % 4;
return decode_base64($s);
}
1;

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Common::PSGI;
use 5.10.0;
use strict;
use Mouse;
use JSON;
use Lemonldap::NG::Common::IO::Filter;
@ -259,7 +259,7 @@ sub sendJs {
return [
200,
[
'Content-Type' => 'application/json',
'Content-Type' => 'application/javascript',
'Content-Length' => length($s),
'Cache-Control' => 'public,max-age=2592000',
],

View File

@ -1,5 +1,6 @@
package Lemonldap::NG::Common::PSGI::Cli::Lib;
use strict;
use JSON;
use Mouse;
use Lemonldap::NG::Common::PSGI;

View File

@ -1,7 +1,6 @@
package Lemonldap::NG::Common::PSGI::Request;
use strict;
use 5.14.0;
use Mouse;
use JSON;
use Plack::Request;

View File

@ -1,5 +1,6 @@
package Lemonldap::NG::Common::PSGI::Router;
use strict;
use Mouse;
use Lemonldap::NG::Common::PSGI;
use Lemonldap::NG::Common::PSGI::Constants;

View File

@ -5,6 +5,8 @@
# SOAP wrapper used to restrict exported functions
package Lemonldap::NG::Common::PSGI::SOAPService;
use strict;
require SOAP::Lite;
our $VERSION = '2.1.0';
@ -28,7 +30,7 @@ sub new {
# @return data provided by the exported function
sub AUTOLOAD {
my $self = shift;
$AUTOLOAD =~ s/.*:://;
our $AUTOLOAD =~ s/.*:://;
if ( grep { $_ eq $AUTOLOAD } @{ $self->{func} } ) {
my $tmp = $self->{obj}->$AUTOLOAD( $self->{req}, @_ );
unless ( ref($tmp) and ref($tmp) =~ /^SOAP/ ) {

View File

@ -10,8 +10,7 @@ use Encode;
use MIME::Base64;
use Lemonldap::NG::Common::IPv6;
use JSON::XS;
#use AutoLoader qw(AUTOLOAD);
use Date::Parse;
our $VERSION = '2.1.0';
@ -19,7 +18,7 @@ our $VERSION = '2.1.0';
# Not that only functions, not methods, can be written here
our $functions =
[
qw(&checkLogonHours &date &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri &has2f)
qw(&checkLogonHours &date &dateToTime &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri &has2f)
];
## @function boolean checkLogonHours(string logon_hours, string syntax, string time_correction, boolean default_access)
@ -122,34 +121,51 @@ sub date {
return $year . $mon . $mday . $hour . $min . $sec;
}
## @function integer dateToTime(string date)
# Converts a LDAP date into epoch time or returns undef upon failure.
# @param $date string Date in YYYYMMDDHHMMSS[+/-0000] format. It may contain a differential timezone, otherwise default TZ is GMT
# @return Date converted to time
sub dateToTime {
my $date = shift;
return undef unless ( $date );
# Parse date
my ( $year, $month, $day, $hour, $min, $sec, $zone ) = ( $date =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})([-+\w]*)/ );
# Convert date to epoch time with GMT as default timezone if date contains none
return str2time( $year . "-" . $month . "-" . $day . "T" . $hour . ":" . $min . ":" . $sec . $zone, "GMT" );
}
## @function boolean checkDate(string start, string end, boolean default_access)
# Function to check a date
# @param $start string Start date (GMT)
# @param $end string End date (GMT)
# @param $default_access optional what result to return for users without start or end start
# @param $start string Start date in YYYYMMDDHHMMSS[+/-0000] format. It may contain a differential timezone, otherwise default TZ is GMT
# @param $end string End date in YYYYMMDDHHMMSS[+/-0000] format. It may contain a differential timezone, otherwise default TZ is GMT
# @param $default_access optional what result to return for users without start and end dates
# @return 1 if access allowed, 0 else
sub checkDate {
my ( $start, $end, $default_access ) = @_;
# Get date in string
$start = substr( $start, 0, 14 );
$end = substr( $end, 0, 14 );
# Default access if no value
$default_access ||= "0";
return $default_access unless ( $start or $end );
# If no start, set start to 0
$start ||= 0;
# If no start, set start to 01 01 1970
$start ||= "19700101000000";
# If no end, set end to the end of the world
$end ||= 999999999999999;
$end ||= "99991231235959";
# Get the present day and hour
my $date = &date;
# Convert dates to epoch time
my $starttime = &dateToTime($start);
my $endtime = &dateToTime($end);
return 1 if ( ( $date >= $start ) and ( $date <= $end ) );
# Convert current GMT date to epoch time
my $datetime = &dateToTime(&date(1));
return 1 if ( ( $datetime >= $starttime ) and ( $datetime <= $endtime ) );
return 0;
}
## @function string basic(string login, string password)
@ -195,7 +211,6 @@ sub iso2unicode {
# @return int Number of values that match
sub groupMatch {
my ( $groups, $attribute, $value ) = @_;
my $match = 0;
foreach my $group ( keys %$groups ) {
@ -208,6 +223,7 @@ sub groupMatch {
$match++ if ( $groups->{$group}->{$attribute} =~ /$value/ );
}
}
return $match;
}
@ -215,6 +231,7 @@ sub isInNet6 {
my ( $ip, $net ) = @_;
$net =~ s#/(\d+)##;
my $bits = $1;
return net6( $ip, $bits ) eq net6( $net, $bits ) ? 1 : 0;
}
@ -229,21 +246,20 @@ my $json = JSON::XS->new;
sub has2f {
my ( $session, $type ) = @_;
return 0 unless ( $session->{_2fDevices} );
return 0 unless $session->{_2fDevices};
my $_2fDevices = eval { $json->decode( $session->{_2fDevices} ); };
return 0 if ( $@ or ref($_2fDevices) ne "ARRAY" );
my $length = scalar @{$_2fDevices};
# Empty array
return 0 unless $length;
return 0 unless scalar @{$_2fDevices};
# Array has one value and we did not specify a type, succeed
if ($type) {
my @found = grep { lc( $_->{type} ) eq lc($type) } @{$_2fDevices};
return ( @found ? 1 : 0 );
return @found ? 1 : 0;
}
return 1;
}

View File

@ -6,10 +6,11 @@
package Lemonldap::NG::Common::Session;
our $VERSION = '2.1.0';
use strict;
use Lemonldap::NG::Common::Apache::Session;
our $VERSION = '2.1.0';
# Workaround for another ModPerl/Mouse issue...
BEGIN {
require Mouse;

View File

@ -1,5 +1,6 @@
package Lemonldap::NG::Common::UserAgent;
use strict;
use LWP::UserAgent;
our $VERSION = '2.1.0';

View File

@ -1,12 +1,11 @@
package Lemonldap::NG::Common::Util;
require Exporter;
use strict;
use Digest::MD5;
use MIME::Base64 qw/encode_base64/;
use 5.10.0;
our $VERSION = '2.1.0';
our $VERSION = '2.0.10';
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(getSameSite getPSessionID genId2F);

Some files were not shown because too many files have changed in this diff Show More