SSO für Web-Anwendungen mittels SAML und Kerberos für Windows Systeme mit Citrix ADC

Web-Anwendungen wie Salesforce, SAP, Slack, O365, Confluence, Jira werden immer mehr genutzt. Dabei kommt meist SAML zum Einsatz damit sich Benutzer mit ihren Active Directory Zugangsdaten gegenüber einem vertrauenswürdigen Identity Provider (IDP) ggf. auch mittels Multifaktor Authentifizierung anmelden können.

 

Benutzer im Unternehmensnetzwerk oder VPN von meinem domain-joined System sind bereits authentifiziert an ihrem Endgerät. Daher ist hier ein sicheres Single Sign On in die SAML Web-Anwendung möglich, ohne dass der Benutzer seine Zugangsdaten eingeben muss.  

 Umgebungsbeschreibung (beispielhaft):

- Web-Anwendung (SP) https://my12345-sso.sapbydesign.com

- ADC AAA FQDN https://aaa.itcma.net

- ADC AAA IP 10.20.30.40

- Active Directory Domain itcma.local

- aaa.itcma.net ist ein CNAME im DNS von aaa.itcma.local

- Key Distribution Center Server dev-dc01.itcma.local

- Internet Explorer Zone "Intranet" beinhaltet "https://aaa.itcma.local"

- Proxy-Ausnahmen vorhanden für dev-dc01.itcma.local oder allgemein lokale Adressen

Ablauf der Anmeldung

Zum Verständnis der Anmeldeverhaltens wird dies hier kurz aufgezeigt. Ein Benutzer itcma.local\username1 sitzt im Unternehmen an seinem Firmennotebook und startet den Browser...

  1. Im Browser wird die Seite https://my12345-sso.sapbydesign.com aufgerufen.
  2. Der SAML SP beantwortet die Anfrage mit HTTP 302 - eine Umleitung zu https://aaa.itcma.net/saml/login
  3. Der Browser ruft die Seite auf und erreicht den SAML IDP - einen AAA vServer auf Citrix ADC 
  4. Der AAA vServer hat eine Negotiate Policy (Kerberos) gebunden. Wenn der Benutzer nicht authentifiziert ist wird HTTP 401 Unauthorized an den Browser zurück gesendet inkl. der Info welche Authentifizierungsmethoden erlaubt sind. 
       - WWW-Authenticate: Negotiate
       - WWW-Authenticate: NTLM
    Negotiate ist für die Kerberos Authentifizierung maßgeblich. 
  5. Da DNS Eintrag aaa.itcma.net ein CNAME ist für den A-Record aaa.itcma.local, versucht der Client eine Verbindung zum Key Distribution Center (KCD) dev-dc01.itcma.local herzustellen. Hierfür muss eine Netzwerk- oder VPN-Verbindung bestehen und eine Proxy-Ausnahme vorhanden sein. Wichtig: Wenn der DNS Eintrag kein CNAME wäre, so würde der Client versuchen den KCD in itcma.local zu erreichen den es nicht gibt. Falls die interne und externe Domäne den gleichen FQDN verwenden, so muss dies ebenfalls beachtet werden.
  6. Die Client-Anfrage wird am KCD Server für HTTP\aaa.itcma.local gestellt. Wenn der SPN im Active Directory existiert erstellt der KCD ein Kerberos-Ticket für den Benutzer, verschlüsselt es mit dem Passwort des AD-Servicekontos netscaler-krb und antwortet mit dem Kerberos-Ticket (TGS) an den Client.
  7. Nun sendet der Client die HTTP Anfrage erneut an AAA vServer inkl. des Kerberos-Tickets.
  8. Der AAA vServer entschlüsselt das Kerberos-Ticket mit dem AD-Konto netscaler-krb (hinterlegt im Citrix ADC). Sollte dies erfolgreich sein wird die Kerberos-Authentifizierung akzeptiert.

    Anschließend extrahiert der AAA vServer aus dem Kerberos-Ticket den Domänen-Benutzernamen des Endanwenders. Hiermit werden über LDAP-Anfrage die Attribute mail, samAccountName, distinguishedName und userPrincipalName des Benutzers abgefragt und zwischengespeichert (ADC Attribute 1 bis 4).

    Nun erzeugt der AAA vServer für den Benutzer das SAML Ticket und integriert die zwischengespeicherten Benutzer-Attribute. Das SAML Ticket wird an den Client gesendet inkl. einer Weiterleitung via HTTP 301 an https://my12345-sso.sapbydesign.com. 
  9. Der Client sendet das SAML Ticket weiter an https://my12345-sso.sapbydesign.com. Das Zielsystem extrahiert die Email-Adresse und verknüpft diese mit dem passenden Benutzer-Konto in der Zielumgebung. Anschließend erzeugt der SP das Web Session Cookie für den Benutzer. Damit ist der Benutzer an der Webseite authentifiziert und diese nutzen.

Zusammengefasst: Der Benutzer muss während der ganzen Anmeldung an der Web-Anwendung keinerlei Aktion durchführen, keine Zugangsdaten eingeben und das Single-Sign-On verläuft vollständig transparent. 

 

Vorgehen

Die Einrichtung erfolgt an mehreren Stellen - vor allem auf dem Citrix ADC ausführlich beschrieben unten. Vorab müssen Active Directory und DNS angepasst werden war hier kurz beschrieben wird.

 

Active Directory

Der Citrix ADC benötigt ein Dienste-Konto im Active Directory und passenden SPN. Das Konto netscaler-krb wird dazu erstellt und die Option "Kennwort läuft nie ab" wird gesetzt. Das ist wichtig, da dieses Dienste-Konto auf dem Citrix ADC hinterlegt wird. 

 

Anschließend muss für das Konto der SPN registriert werden. Dies erfolgt über eine CMD mit Administratorrechten mit dem Befehl: set-spn -A HTTP/aaa.itcma.local   itcma\netscaler-krb

 

Über die Konto-Attribute lässt sich prüfen ob der Wert passend gesetzt wurde.

 

Internes DNS

Hier wird es interessant da wir für die interne DNS Zonen einen CNAME Record erzeugen müssen. Der CNAME ist von besonderer Bedeutung! Wenn wir im Beispiel für aaa.itcma.net einen A-Record anlegen würden, versucht der Client das Key Distribution Center für itcma.net zu erreichen - was nicht funktioniert. Da CNAME-Records magisch sind können diese hier wundervolles tun. Sie sorgen dafür, dass richtig angewendet der passende KCD angesprochen wird.

 

Dazu im ersten Schritt auf dem internen DNS Server für die interne Zone itcma.local einen A-Record erzeugen für den AAA Server aaa.itcma.net wie hier gezeigt:

 

Als zweites den CNAME-Record aaa.itcma.net erstellen mit dem Ziel aaa.itcma.local. Damit ist die DNS Einrichtung abgeschlossen.

 

Citrix ADC

Starten wir zu Beginn ganz einfach mit dem Anlegen des AAA vServers. 

  • add authentication vserver AAA_SAML_SAP SSL 10.10.10.150 443 -appflowLog DISABLED
  • bind ssl vserver AAA_SAML_SAP -certkeyName <AAA-Cert>

 

Die Kerberos Authentifizierung sieht wie folgt aus. Dabei ist die Domain unwichtig und kann beliebig gesetzt werden. Der DomainUser sollte lauten wie der SPN ohne HTTP/ - also in diesem Fall aaa.itcma.local. Zusätzlich muss das Kennwort des Dienst-Kontos netscaler-krb angegeben werden.

  • add authentication negotiateAction AAA_Act_NEGOTIATE -domain dummy -domainUser aaa.itcma.local -domainUserPasswd <Passwort des Dienstekontos von 'netscaler-krb'>
  • add authentication Policy AAA_Pol_NEGOTIATE -rule true -action AAA_Act_NEGOTIATE 

 

LDAP extrahiert die Benutzer-Attribute und Gruppenmitgliedschaften bei der Anmeldung. Dabei ist folgendes zu beachten:

  1. Es erfolgt keine Authentifizierung sondern nur eine Abfrage über die LDAP-Action da -authentication DISABLED gesetzt ist. Dies ist nicht erforderlich und zudem nicht möglich, da der ADC das Benutzer-Kennwort nicht kennt
  2. Es werden die Benutzer Attribute mail, sAMAccountName und userPrincipalName extrahiert und die die ADC Attribute 1-3 zwischengespeichert damit diese für die SAML-Antwort verwendet werden können
  3. Via nestedGroupExtraction bis Level 3 werden verschachtelte Gruppenmitgliedschaften enumeriert
  • add authentication ldapAction AAA-AS-LDAP_NEGOTIATE_GROUP_EXTRACTION -serverIP <LB Domain-Controller> -serverPort 636 -authTimeout 5 -ldapBase "DC=itcma,DC=local" -ldapBindDn netscaler-ldap-svc@itcma.local -ldapBindDnPassword <Passwort des netscaler-ldap-svc Kontos> -ldapLoginName sAMAccountName -groupAttrName memberOf -subAttributeName CN -secType SSL -ssoNameAttribute sAMAccountName -authentication DISABLED -nestedGroupExtraction ON -maxNestingLevel 3 -groupNameIdentifier samAccountName -groupSearchAttribute memberOf -groupSearchSubAttribute CN -Attribute1 mail -Attribute2 sAMAccountName -Attribute3 userPrincipalName
  • add authentication Policy AAA_Pol_LDAP_NEGOTIATE_GROUP_EXTRACTION -rule "true" -action AAA-AS-LDAP_NEGOTIATE_GROUP_EXTRACTION

 

Die SAML Einrichtung sieht wie folgt aus. Dabei kommen wieder die ADC Attribute zum Einsatz von LDAP - siehe HTTP.REQ.USER.ATTRIBUTE(X)

  • add authentication samlIdPProfile AAA_SAMLIDP_Prof_SAPbyDesign -samlSPCertName <SAML-SAP-Cert> -samlIdPCertName <SAML-ITCMA-Cert> -assertionConsumerServiceURL "https://my12345-sso.sapbydesign.com/auth/saml2" -samlIssuerName ITCMA-ADC -audience "https://my12345-sso.sapbydesign.com" -NameIDFormat Unspecified -Attribute1 userEmailAddress -Attribute1Expr "HTTP.REQ.USER.ATTRIBUTE(1)" -Attribute1FriendlyName userEmailAddress -Attribute2 samAccountName -Attribute2Expr "HTTP.REQ.USER.ATTRIBUTE(2)" -Attribute2FriendlyName samAccountName -Attribute3 UPN -Attribute3Expr "HTTP.REQ.USER.ATTRIBUTE(3)" -Attribute3FriendlyName UPN -skewTime 15 -serviceProviderID "https://my12345-sso.sapbydesign.com" -SPLogoutUrl "https://my12345-sso.sapbydesign.comauth/saml2-logout" -logoutBinding REDIRECT
  • add authentication samlIdPPolicy AAA_SAMLIDP_Pol_SAPbyDesign -rule "HTTP.REQ.URL.PATH.SET_TEXT_MODE(IGNORECASE).EQ(\"/saml/login\")" -action AAA_SAMLIDP_Prof_SAPbyDesign
  • bind authentication vserver AAA_SAML_SAP -policy AAA_SAMLIDP_Pol_SAPbyDesign -priority 100 -gotoPriorityExpression NEXT

 

Nun wird per nFactor alles zusammengeführt. Dabei wird im ersten Schritt die Kerberos Authentifizierung durchgeführt, anschließend via LDAP die Attribute extrahiert und zum Schluss das SAML Ticket bereitgestellt. Dabei zeigt sich auch warum die Benutzer-Attribute zwischengespeichert werden mussten. Denn der Benutzername der aus dem Kerberos-Ticket extrahiert wird liegt als sAMAccountName vor. Über die nFactor-Verkettung werde anschließend für den Benutzer die Attributen extrahiert die in das SAML Ticket integriert werden müssen wie z.B. die Email-Adresse/userPrincipalName.

  • add authentication loginSchema LSCHEMA_INT_NEGOTIATE_SSO -authenticationSchema noschema -userExpression "AAA.USER.NAME.BEFORE_STR(\"@\")"
  • add authentication Policy AAA_AdvPol_NEGOTIATE -rule "true" -action AAA_Act_NEGOTIATE
  • add authentication Policy AAA_AdvPol_TRUE_DUMMY -rule true -action NO_AUTHN
  • add authentication policylabel AAA_PolLabel_LDAP_NEGOTIATE_GROUP_EXTRACTION -loginSchema LSCHEMA_INT_NEGOTIATE_SSO
  • bind authentication policylabel AAA_PolLabel_LDAP_NEGOTIATE_GROUP_EXTRACTION -policyName AAA_Pol_LDAP_NEGOTIATE_GROUP_EXTRACTION -priority 100 -gotoPriorityExpression NEXT
  • add authentication policylabel AAA_PolLabel_NEGOTIATE_SSO -loginSchema LSCHEMA_INT
  • bind authentication policylabel AAA_PolLabel_NEGOTIATE_SSO -policyName AAA_AdvPol_NEGOTIATE -priority 100 -gotoPriorityExpression NEXT -nextFactor AAA_PolLabel_LDAP_NEGOTIATE_GROUP_EXTRACTION
  • bind authentication vserver AAA_SAML_SAP -policy AAA_AdvPol_TRUE_DUMMY -priority 100 -nextFactor AAA_PolLabel_NEGOTIATE_SSO -gotoPriorityExpression NEXT

 

Damit ist die Einrichtung abgeschlossen und kann getestet werden. Sollte alles passen wird der Benutzer keinen Anmeldebildschirm oder Abfragen erhalten wenn die SAP-Seite aufgerufen wird.

 

Analyse

Oftmals macht der Proxy beim Aufruf des Key Distribution Centers Schwierigkeiten. Darauf achten, dass die Adresse in der Proxy-Ausnahmenliste aufgeführt ist. Auf der Client kann zudem geprüft werden über die Command-Line ob ein Kerberos-Ticket erzeugt wurde für den Server. Der Befehl dazu lautet klist. Sollte kein Server-Eintrag für HTTP/aaa.itcma.local vorhanden sein, so wurde auch kein Ticket erzeugt.

 

Hierbei kann es helfen einen Wireshark Trace zu erzeugen auf dem Client. Um dabei auf Kerberos zu filtern tcp.port == 88 verwenden. Dadurch wird der komplette Verkehr zwischen dem Client und KCD angezeigt.

 

Üblicherweise sind die internen FQDN's auch im Internet Explorer definiert als "Lokales Intranet". Sollte im Browser des Clients eine Windows Basic Anmeldung erscheinen so könnte die Eintrag fehlen. Entsprechend unter Sites aaa.itcma.local hinterlegen.

 

Diese Einstellung ist übrigens unabhängig davon welcher Browser verwendet wird und ist immer nötig. Ebenfalls kann eine Windows Basis Anmeldung erscheinen, wenn das Kennwort des Kerberos Benutzers falsch ist. Dieses entsprechend prüfen und ggf. im Eventlog des KCD nach Meldungen schauen.

 

Sollte hingegen die die Form-Based Anmeldung des AAA vServers erscheinen (siehe Screenshot) so konnte der Client den KCD nicht erreichen.

 

Der Citrix ADC unterstützt keine Kerberos Verschlüsselung mit AES-128 und AES-256 für den Dienste-Benutzer netscaler-krb. Daher im AD-Objekt sicher stellen dass die Optionen nicht aktiviert sind.