CAS Authentication Server
CAS Authentication Server
Der CAS Server ("Central Authentication Service" oder "CAS Authentication Server") ist eine SSO- ("Single Sign On") Lösung.
CAS ist für große, verteilte Deploments von Web-Anwendungen geeignet. Er stammt aus dem Universitätsumfeld in den USA. Er wurde bei der Yale Universität entwickelt und wird aktuell bei JA-SIG / Apereo als freie Software unter der Apache Lizenz gepflegt. [1], [2]
Die Hostsharing eG nutzt CAS seit Jahren als Login-Lösung insbesondere für die Administrationswerkzeuge von Hsadmin.
Dieser Beitrag erläutert die Installation von CAS in einem Hostsharing Webspace und die Konfiguration von Beispielanwendungen zum Login mit CAS. Als Nutzerdatenbank wird ein vorhandener Nutzerstamm in einer SQL-Datenbank benutzt,
Erste Installation
Die aktuelle stabile Version des CAS Server ist 6.0.4 Diese Version erfordert Java 11. Die empfohlene Installation eines Standalone-CAS erfolgt über das WAR Overlay Projekt [3]. Eine ausführliche Deployment-Anleitung (leider noch für Version 5.x) findet sich bei The New School [4].
Service-User und Domain
Zunächst werden mit HSAdmin ein User und eine Domain eingerichtet. Darauf achten, dass der User eine gültige Login-Shell erhält, hier die Bash (/bin/bash).
xyz00@h50:~$ hsscript -i xyz00@hsadmin> user.add({set:{name:'xyz00-login',shell:'/bin/bash',password:'***'}}) xyz00@hsadmin> domain.add({set:{user:'xyz00-login',name:'login.hs-example.de'}}) xyz00@hsadmin> bye
Einrichtung des Tomcat
Für den Apache Tomcat Webserver ist die Option "Eigener Daemon" notwendig. Bei der Anmeldung (bei service(at)hostsharing.net bitte den Service User xyz00-login und die gewüschte Anzahl IP-Ports angeben). Hier verwenden wir die Ports 31530, 31531 und 31532.
Weiter geht es als User xyz00-login
Einrichten eines Apache Tomcat 9 im Userspace:
xyz00-login@h50:~$ tomcat9-instance-create tomcat9 You are about to create a Tomcat instance in directory 'tomcat9' Warning: HTTP port 8080 appears to be in use. Type <ENTER> to continue, <CTRL-C> to abort.
Mit <Enter> bestätigen, dann wird eine Tomcat-Konfiguration im neuen Verzeichnis $HOME/tomcat9 angelegt.
Die server.xml im Verzeichnis $HOME/tomcat9/conf wird angepasst:
<?xml version="1.0" encoding="UTF-8"?> <Server port="31530" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <GlobalNamingResources> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <Service name="Catalina"> <Connector address="localhost" port="31531" protocol="AJP/1.3" redirectPort="443" /> <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> </Host> </Engine> </Service> </Server>
Insbesondere die beiden Angaben port="31530" und port="31531" müssen angepasst werden!
In der Datei setenv.sh im Verzeichnis $HOME/tomcat9/bin ergänzenen wir den Pfad zur Java 11 Installation als Variable $JAVA_HOME (für 32-Bit bzw. für 64-Bit Systeme), dazu den Pfad für eine Datei mit der Prozess-ID Prozess-Id und eine System-Property in den Java-Opts mit dem Verzeichnis-Pfad, in dem wir später die CAS-Konfiguration ablegen:
# export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-i386 export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 export JAVA_OPTS="-Djava.awt.headless=true -Dcas.standalone.configurationDirectory=/home/pacs/xyz00/users/login/cas/conf"
Ich kopiere zum Testen gern noch das Startskript catalina.sh in die Installation des Tomcat:
Fehler in catalina.sh
Zur Zeit ist in der catalina.sh des Debian-Tomcat-9 ein Fehler, der dazu führt, dass die Datei catalina.pid nicht geschrieben wird. Bitte in den Zeilen 479 und 489 der catalina.sh jeweils ein "\&" aus dem doppelten "\&\&" herauslöschen!
xyz00-login@h50:~$ cp /usr/share/tomcat9/bin/catalina.sh $HOME/tomcat9/bin/ xyz00-login@h50:~$ cd tomcat9/ xyz00-login@h50:~/tomcat9$ ./bin/catalina.sh run Using CATALINA_BASE: /home/pacs/xyz00/users/login/tomcat9 Using CATALINA_HOME: /usr/share/tomcat9 Using CATALINA_TMPDIR: /home/pacs/xyz00/users/login/tomcat9/temp Using JRE_HOME: /usr/lib/jvm/default-java Using CLASSPATH: /usr/share/tomcat9/bin/bootstrap.jar:/usr/share/tomcat9/bin/tomcat-juli.jar <6>Server version name: Apache Tomcat/9.0.16 (Debian) [...] <6>Server startup in [75] milliseconds
Tomcat läuft, abbrechen mit <Ctrl-C>
Konfiguration des Apache als Proxy
cd ~/doms/login.hs-example.de/ rm -rf subs/www subs-ssl/www
Bearbeiten der ~/doms/login.hs-example.de/htdocs-ssl/.htaccess
DirectoryIndex disabled RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^(.*) ajp://localhost:31531/$1 [proxy,last]
Achtung: der Port 31531 ist wieder durch den Port des AJP-Listeners in der eigenen Tomcat-Konfiguration zu ersetzen.
CAS Basisinstallation
Anlegen von Verzeichnissen für die spätere Konfiguration des CAS Server
cd mkdir -p cas/conf mkdir -p cas/services
Ins Verzeichnis ~/cas/conf legen wir eine Datei cas.properties mit folgendem Inhalt:
cas.server.name=https://login.hs-example.de cas.server.prefix=${cas.server.name}/cas cas.serviceRegistry.json.location=file:/home/pacs/xyz00/users/login/cas/services logging.config=file:/home/pacs/xyz00/users/login/cas/conf/log4j2.xml
Die Datei log4j2.xml kopieren wir aus ~/git/cas-overlay-template/etc/cas/config/
cp ~/git/cas-overlay-template/etc/cas/config/ ~/cas/conf/
In der log4j2.xml passen wir den Wert für die Variable baseDir (etwa Zeile 5) an:
<Property name="baseDir">/home/pacs/xyz00/users/login/tomcat9/logs</Property>
Auschecken des CAS Overlay Projektes
mkdir git cd git git clone https://github.com/apereo/cas-overlay-template.git cd cas-overlay-template/ git fetch git checkout 6.0
Build und Deployment der Web-Applikation
./build.sh package cd cp ~/git/cas-overlay-template/build/libs/cas.war ~/tomcat9/webapps/
Nach einer erneuten Start des Tomcat ist das CAS-Login unter https://login.hs-example.de/cas/ erreichbar.
Ein Login mit der Kennung casuser und dem Passwort Mellon sollte erfolgreich sein.
Erweiterte Konfiguration des CAS
Die Funktionalität des CAS Server ist modular erweiterbar. Im ersten Schritt erweitern wir den CAS um eine Service Registry. Für unsere einfache Standalone-Installation nutzen wir die JSON-File-Registry
JSON Service Registry
Erweiterungen werden in der Datei build.gradle im Abschnitt dependencies eingetragen. Die Datei liegt im Wurzelverzeichnis des Git-Repositories für unser CAS Overlay (~/git/cas-overlay-template/).
Der betreffende Ausschnitt der Datei:
dependencies { compile "org.apereo.cas:cas-server-webapp${project.appServer}:${casServerVersion}" // Other CAS dependencies/modules may be listed here... compile "org.apereo.cas:cas-server-support-json-service-registry:${project.'cas.version'}" }
Wir bauen das cas.war mit den folgenden Befehlen neu:
cd ~/git/cas-overlay-template ./build.sh package cp ~/git/cas-overlay-template/build/libs/cas.war ~/tomcat9/webapps/
Der Pfad zur Service-Registry war in der oben erstellten cas.properties bereits enthalten. Nun legen wir einen ersten Service an, in meinem Fall eine Nextcloud-Installation. Die Datei heißt hsexamplecloud-1000001.json und wird im Verzeichnis ~/cas/services/ abgelegt. Der Inhalt:
{ "@class" : "org.apereo.cas.services.RegexRegisteredService", "serviceId" : "^https://cloud.hs-example.de.*", "name" : "hsexamplecloud", "id" : 1000001, "description" : "Nextcloud HS-Example", "evaluationOrder" : 10000 }
Der Name der Datei setzt sich aus Service-Name und Service-Id zusammen!
Die Konfiguration des CAS-Login in der Nextcloud erfolgt über die entsprechende "App" in Nextcloud. Die Parameter sind wie folgt:
Die "Dienst-URL" im Screenshot ist: https://cloud.hs-example.de/index.php/apps/user_cas/login
Die Anmeldung mit der Kennung casuser und dem Passwort Mellon sollte nun von der Nextcloud-Loginseite über den Link zum CAS-Login möglich sein.
Authentifizierung gegen JDBC Datenbank
Wir erweitern wieder die Datei build.gradle im Abschnitt dependencies.
dependencies { compile "org.apereo.cas:cas-server-webapp${project.appServer}:${casServerVersion}" // Other CAS dependencies/modules may be listed here... compile "org.apereo.cas:cas-server-support-json-service-registry:${project.'cas.version'}" compile "org.apereo.cas:cas-server-support-jdbc-drivers:${project.'cas.version'}" compile "org.apereo.cas:cas-server-support-jdbc:${project.'cas.version'}" }
cas-server-support-jdbc-drivers liefert JDBC-Treiber für die gängigen Open-Source Datenbanksysteme. org.apereo.cas:cas-server-support-jdbc liefert das eigentliche CAS-Authentication Backend.
Zur Konfiguration wird die Datei cas.properties im Verzeichnis ~/cas/conf/ erweitert:
cas.server.name=https://login.hs-example.de cas.server.prefix=${cas.server.name}/cas cas.serviceRegistry.json.location=file:/home/pacs/xyz00/users/login/cas/services logging.config=file:/home/pacs/xyz00/users/login/cas/conf/log4j2.xml logging.level.org.apereo=DEBUG cas.authn.jdbc.query[0].sql=SELECT * FROM USERS WHERE UID=? cas.authn.jdbc.query[0].url=jdbc:postgresql://localhost/xyz00_cas cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.PostgreSQL92Dialect cas.authn.jdbc.query[0].user=xyz00_cas cas.authn.jdbc.query[0].password=Ein_schlechtes_Passwort cas.authn.jdbc.query[0].driverClass=org.postgresql.Driver cas.authn.jdbc.query[0].fieldPassword=PSW cas.authn.jdbc.query[0].passwordEncoder.type=BCRYPT cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8 cas.authn.accept.users=
Hier ein Beispiel für eine PostgreSQL-Datenbank mit einer Tabelle USERS mit den Spalten UID und PSW. Die Spalte UID enthält den Login-Namen des Users, die Spalte PSW das Passwort mit dem BCrypt-Algorithmus verschlüsselt.
Die Zeile cas.authn.accept.users= deaktiviert das Default-Login als User casuser mit Passwort Mellon.
Achtung: Das Spring-Security Framework erwartet das BCrypt-Passwort mit der Kennung $2a$ als erste Zeichen des Passwortfeldes. Die PHP-Funktion password_hash schreibt $2y$ Wenn eine PHP-Passwort-Datenbank genutzt wird, muss hier ggf. eine VIEW in der Datenbank helfen.
Links
[1] https://de.wikipedia.org/wiki/Central_Authentication_Service
[2] https://www.apereo.org/projects/cas
[3] https://github.com/apereo/cas-overlay-template
[4] https://dacurry-tns.github.io/deploying-apereo-cas/
[5] https://apereo.github.io/2017/02/22/cas51-dbauthn-tutorial/