-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cas - adding a sample compo to test password policies
- Loading branch information
Showing
6 changed files
with
267 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# About | ||
|
||
This docker composition provides a way to test the password rotation policy | ||
from the LDAP, and how it affects the templates on CAS when one to try to log | ||
in with an expired account. | ||
|
||
# Ports | ||
|
||
* CAS is available on port 8080 | ||
* LDAP is available on port 3389 | ||
|
||
# scenario | ||
|
||
a georchestra/ldap is launched along with the environment variable | ||
`SLAPD_PASSWORD_MGT_POLICY` set to `rotation`. | ||
|
||
When the LDAP server bootstraps, a `docker-entrypoint.d` init script injects a | ||
new password policy which makes the passwords expiring after 2 seconds, and | ||
affects this new policy to the `testuser` account. | ||
|
||
2 seconds is probably enough to have the passwords for the user expired before | ||
being able to log in as `testuser`. | ||
|
||
After having launched the composition, if you visit | ||
`http://localhost:8080/cas/login`, and try to connect as `testuser/testuser`, | ||
you should see a message telling you that your password expired, along with a | ||
link to the console (not provided by the composition) so that you could reset | ||
it. | ||
|
||
# More technical details | ||
|
||
The password policy management in OpenLDAP is performed via an overlay, see | ||
[official documentation](https://www.openldap.org/devel/admin/overlays.html), | ||
chapter 12.10. | ||
|
||
Once the overlay is loaded into `slapd`, you can add the `pwdPolicySubentry` | ||
operational attribute to your users, and the attribute has to point onto an | ||
existing policy, loaded under `ou=pwpolicy,dc=georchestra,dc=org`. | ||
|
||
geOrchestra provides 2 password policies by default: | ||
|
||
* a `cn=pwd-no-expire`, mainly reserved to bot accounts, which does not | ||
define an expiration date for passwords (`pwdMaxAge: 0`). | ||
* a `cn=default`, which makes the user passwords expiring after 6 months. | ||
|
||
As the `pwdPolicySubentry` is an operational attribute (managed by slapd and | ||
not complying to the regular LDAP schemas), the attribute won't appear when | ||
listing the users' entry as LDIF, if not requested explicitely. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
services: | ||
ldap: | ||
image: georchestra/ldap:latest | ||
environment: | ||
- SLAPD_PASSWORD_MGT_POLICY=rotation | ||
ulimits: | ||
nofile: | ||
soft: "1024" | ||
hard: "1024" | ||
volumes: | ||
- ./resources/ldap/docker-entrypoint.d/99-update-password-expiration.sh:/docker-entrypoint.d/99-update-password-expiration.sh | ||
ports: | ||
- "3389:389" | ||
|
||
cas: | ||
image: georchestra/cas:latest | ||
volumes: | ||
- ./resources/datadir:/etc/georchestra | ||
ports: | ||
- "8080:8080" |
51 changes: 51 additions & 0 deletions
51
cas/password-expiration/resources/datadir/cas/config/cas.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
cas.server.name=http://localhost:8080 | ||
cas.server.prefix=${cas.server.name}/cas | ||
|
||
logging.config=file:/etc/georchestra/cas/config/log4j2.xml | ||
cas.theme.param-name=georchestra | ||
cas.theme.default-theme-name=georchestra | ||
|
||
cas.service-registry.core.init-from-json=false | ||
cas.service-registry.json.location=file:/etc/georchestra/cas/services | ||
#uncomment if getting 302 redirects on cas.{css,js} behind nginx/apache | ||
server.forward-headers-strategy=FRAMEWORK | ||
|
||
cas.authn.accept.enabled=false | ||
|
||
cas.authn.ldap[0].ldap-url=ldap://ldap:389/ | ||
cas.authn.ldap[0].bind-dn= | ||
cas.authn.ldap[0].bind-credential= | ||
|
||
cas.authn.ldap[0].base-dn=dc=georchestra,dc=org | ||
cas.authn.ldap[0].subtree-search=true | ||
cas.authn.ldap[0].search-filter=uid={user} | ||
cas.authn.ldap[0].page-size=0 | ||
|
||
cas.authn.ldap[0].pool-passivator=NONE | ||
cas.authn.ldap[0].connection-strategy= | ||
cas.authn.ldap[0].connect-timeout=PT5S | ||
cas.authn.ldap[0].disable-pooling=false | ||
cas.authn.ldap[0].min-pool-size=3 | ||
cas.authn.ldap[0].max-pool-size=10 | ||
cas.authn.ldap[0].validate-on-checkout=true | ||
cas.authn.ldap[0].validate-periodically=true | ||
cas.authn.ldap[0].validate-period=PT5M | ||
cas.authn.ldap[0].validate-timeout=PT5S | ||
cas.authn.ldap[0].fail-fast=true | ||
cas.authn.ldap[0].idle-time=PT10M | ||
cas.authn.ldap[0].prune-period=PT2H | ||
cas.authn.ldap[0].block-wait-time=PT3S | ||
|
||
cas.authn.ldap[0].use-start-tls=false | ||
cas.authn.ldap[0].response-timeout=PT5S | ||
cas.authn.ldap[0].allow-multiple-dns=false | ||
cas.authn.ldap[0].allow-multiple-entries=false | ||
cas.authn.ldap[0].follow-referrals=false | ||
cas.authn.ldap[0].binary-attributes=jpegPhoto | ||
cas.authn.ldap[0].name= | ||
|
||
cas.authn.ldap[0].type=DIRECT | ||
cas.authn.ldap[0].dn-format=uid=%s,ou=users,dc=georchestra,dc=org | ||
|
||
cas.authn.oidc.jwks.file-system.jwks-file=file:///tmp/keystore.jwksdown | ||
cas.authn.saml-idp.metadata.file-system.location=file:///tmp/ |
90 changes: 90 additions & 0 deletions
90
cas/password-expiration/resources/datadir/cas/config/log4j2.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<!-- Specify the refresh internal in seconds. --> | ||
<Configuration monitorInterval="5" packages="org.apereo.cas.logging"> | ||
<Properties> | ||
<Property name="baseDir">/var/log</Property> | ||
<Property name="cas.log.level">info</Property> | ||
<Property name="spring.webflow.log.level">warn</Property> | ||
<Property name="spring.security.log.level">info</Property> | ||
<Property name="spring.cloud.log.level">warn</Property> | ||
<Property name="spring.boot.admin.log.level">debug</Property> | ||
<Property name="spring.web.log.level">warn</Property> | ||
<Property name="spring.boot.log.level">warn</Property> | ||
<Property name="ldap.log.level">warn</Property> | ||
<Property name="pac4j.log.level">warn</Property> | ||
<Property name="opensaml.log.level">warn</Property> | ||
<Property name="hazelcast.log.level">warn</Property> | ||
</Properties> | ||
<Appenders> | ||
<Console name="console" target="SYSTEM_OUT"> | ||
<PatternLayout pattern="%highlight{%d %p [%c] - <%m>}%n"/> | ||
</Console> | ||
|
||
<CasAppender name="casConsole"> | ||
<AppenderRef ref="console" /> | ||
</CasAppender> | ||
</Appenders> | ||
<Loggers> | ||
<!-- If adding a Logger with level set higher than warn, make category as selective as possible --> | ||
<!-- Loggers inherit appenders from Root Logger unless additivity is false --> | ||
<AsyncLogger name="org.apereo" level="${sys:cas.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.apereo.services.persondir" level="${sys:cas.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.apereo.cas.services" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.apereo.cas.web.flow" level="${sys:cas.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.apereo.spring" level="${sys:cas.log.level}" includeLocation="true"/> | ||
|
||
<AsyncLogger name="org.apache" level="warn" /> | ||
<AsyncLogger name="org.apache.http" level="error" /> | ||
|
||
<AsyncLogger name="org.springframework.boot" level="${sys:spring.boot.log.level" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.boot.context.embedded" level="info" includeLocation="true" /> | ||
<AsyncLogger name="org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration" | ||
level="${sys:spring.security.log.level}" includeLocation="true" /> | ||
<AsyncLogger name="org.springframework.boot.autoconfigure.security" level="${sys:spring.security.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.boot.devtools" level="off" includeLocation="true"/> | ||
|
||
<AsyncLogger name="org.springframework" level="warn" includeLocation="true" /> | ||
<AsyncLogger name="org.springframework.webflow" level="${sys:spring.webflow.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.aop" level="warn" includeLocation="true" /> | ||
<AsyncLogger name="org.springframework.web" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.session" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.scheduling" level="info" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.cloud.vault" level="warn" includeLocation="true" /> | ||
<AsyncLogger name="org.springframework.web.client" level="warn" includeLocation="true" /> | ||
<AsyncLogger name="org.springframework.security" level="${sys:spring.security.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.cloud" level="${sys:spring.cloud.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.amqp" level="error" /> | ||
<AsyncLogger name="org.springframework.integration" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.messaging" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.web" level="${sys:spring.web.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.orm.jpa" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.scheduling" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.context.annotation" level="off" includeLocation="true"/> | ||
<AsyncLogger name="org.springframework.web.socket" level="warn" includeLocation="true"/> | ||
|
||
<AsyncLogger name="org.thymeleaf" level="warn" includeLocation="true"/> | ||
|
||
<AsyncLogger name="org.pac4j" level="${sys:pac4j.log.level}" includeLocation="true"/> | ||
|
||
<AsyncLogger name="org.opensaml" level="${sys:opensaml.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="PROTOCOL_MESSAGE" level="${sys:opensaml.log.level}" includeLocation="true" /> | ||
|
||
<AsyncLogger name="net.sf.ehcache" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="com.couchbase" level="warn" includeLocation="true"/> | ||
<AsyncLogger name="de.codecentric" level="${sys:spring.boot.admin.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="net.jradius" level="warn" includeLocation="true" /> | ||
<AsyncLogger name="org.openid4java" level="warn" includeLocation="true" /> | ||
<AsyncLogger name="org.ldaptive" level="${sys:ldap.log.level}" includeLocation="true"/> | ||
<AsyncLogger name="com.hazelcast" level="${sys:hazelcast.log.level}" includeLocation="true"/> | ||
|
||
|
||
<!-- All Loggers inherit appenders specified here, unless additivity="false" on the Logger --> | ||
<AsyncRoot level="warn"> | ||
<!-- | ||
For deployment to an application server running as service, | ||
delete the casConsole appender below | ||
--> | ||
<AppenderRef ref="casConsole"/> | ||
</AsyncRoot> | ||
</Loggers> | ||
</Configuration> |
Empty file.
58 changes: 58 additions & 0 deletions
58
cas/password-expiration/resources/ldap/docker-entrypoint.d/99-update-password-expiration.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#!/bin/bash | ||
|
||
# start slapd in background | ||
echo -n "Starting slapd daemon in background..." | ||
slapd -u ${RUN_AS_UID} -g ${RUN_AS_GID} -h "ldapi:/// ldap://127.0.0.1/" | ||
echo "Started: OK" | ||
|
||
echo -n "Waiting for LDAP deamon to start..." | ||
while true; do | ||
sleep 1 | ||
ldapsearch -x >/dev/null 2>&1 | ||
if [ $? -eq 0 ]; then | ||
break | ||
fi | ||
done; | ||
echo "Waiting: OK" | ||
|
||
|
||
echo "Adding a 2seconds password expiration policy" | ||
|
||
cat <<EOF | ldapadd -Dcn=admin,dc=georchestra,dc=org -w ${SLAPD_PASSWORD} -x | ||
dn: cn=2secondsexpiration,ou=pwpolicy,dc=georchestra,dc=org | ||
objectClass: person | ||
objectClass: pwdPolicy | ||
objectClass: pwdPolicyChecker | ||
cn: default | ||
cn: pwpolicy | ||
pwdAttribute: userPassword | ||
sn: pwpolicy | ||
pwdExpireWarning: 2592000 | ||
pwdGraceAuthNLimit: 0 | ||
pwdMaxAge: 2 | ||
pwdMinAge: 0 | ||
EOF | ||
|
||
echo "Affecting the 2seconds password expiration policy to testuser" | ||
|
||
cat <<EOF | ldapmodify -Dcn=admin,dc=georchestra,dc=org -w ${SLAPD_PASSWORD} -x | ||
dn: uid=testuser,ou=users,dc=georchestra,dc=org | ||
changetype: modify | ||
add: pwdPolicySubentry | ||
pwdPolicySubentry: cn=2secondsexpiration,ou=pwpolicy,dc=georchestra,dc=org | ||
EOF | ||
|
||
pkill slapd | ||
|
||
# wait for ldap to stop | ||
echo -n "Waiting for LDAP to stop..." | ||
while true; do | ||
sleep 1 | ||
pgrep slapd >/dev/null 2>&1 | ||
if [ $? -ne 0 ]; then | ||
break | ||
fi | ||
done; | ||
echo "Waiting: OK" |