Single-Sign-On mit Kerberos Constrained Delegation
Hallo liebe Leser,
als heutiges Thema möchte ich über ein weiteres Single-Sign-On Verfahren sprechen: Kerberos Constrained Delegation.
Was bedeutet das? Nun was hier passiert, ist dass der User sich am Access Policy Manager (APM) anmeldet. Hier können natürlich verschiedene Verfahren verwendet werden, wie z.B. Client-zertifikatsbasierte Anmeldung, oder Username/Passwort, die Kombination aus beiden oder eben auch andere Methoden. Entscheidend jedenfalls ist, dass sich der User authentifiziert und der Access Policy Manager (APM) anschließend ein Ticket für den User vom Key Distribution Center (KDC) erhält. Dieses Ticket wird dann dem User-Request hinzugefügt, damit am Backend-Server die entsprechende Authentifizierung mittels Kerberos erfolgreich verläuft.
Anwendung findet dieses Verfahren häufig, wenn User aus dem „externen“ Netz zugreifen und somit keine Möglichkeit haben, selber ein Ticket vom KDC zu erhalten.
Damit die BIG-IP aber überhaupt ein Ticket für den User bekommt, muss ein entsprechender Delegation-Account auf dem Domain Controller (DC) angelegt sein. Windows Administratoren fühlen sich hier vermutlich zu Hause. Für alle anderen ein paar Screenshots, die bei dieser Konfiguration hoffentlich helfen:
Der „Advanced View“ im „Active Directory Users and Computers“ ermöglicht es den Attribute Editor unter User Properties auszuwählen.
Nun legen wir einen User-Account an:
User logon name = host/apm.example.com
User logon name pre Windows 2000 = apm.example
Der servicePrincipial Name muss dem DC hinzugefügt werden, bevor man in den Delegation Reiter des User wechselt. Dies kann mit dem Tool „setspn“ oder „adsiedit“ durchgeführt werden:
run adsiedit.msc
Nun den Usernamen auswählen, Properties wählen, und den Eintrag servicePrincipalName auswählen und „host/apm.example.com“ hinzufügen.
Oder man fügt den Principial Name über den Attribute-Editor in den User Eigenschaften hinzu:
Schließt man nun das Property Fenster und öffnet es wieder, hat man Zugriff auf den Delegation Tab. Hier kann man nun die Delegationsrechte für den User auf einen bestimmten Service freigeben. In meinem Beispiel ist es „WIN2008R2.example.com“. Übrigens das ist der Name meines Backend-Servers. Hat man mehrere müssen diese ebenfalls hinzugefügt werden.
Unter den Account Options sollte man nun nochmal überprüfen, dass keine Account Optionen gesetzt sind. Der Delegation User brauch nur Mitglied der „Domain User“ zu sein.
Um zu überprüfen, dass es keine Konflikte in der Kerberos Konfiguration gibt, kann man „setspn –x“ aufrufen:
Wichtig bei dem Thema Kerberos ist, dass man alle DNS Einträge richtig gesetzt hat. Hier bitte alle Adressen und Namen die in dem Zusammenhang verwendet werden in beide Richtungen auflösen. Das kann einem so manches Debugging ersparen.
Ganz wichtig auch: die Zeit! NTP sollte auf der BIG-IP auf jeden Fall eingestellt sein und synchron zum DC sein! DNS sollte natürlich auch funktionieren.
Fassen wir kurz zusammen: Wir haben nun also einen User im DC konfiguriert, der für einen bestimmten Service im Namen eines anderen Nutzers ein Kerberos Ticket erstellen darf. Das ist noch nicht viel, kommen wir nun also zur Konfiguration der BIG-IP. Übrigens die Kerberos Konfiguration des IIS überlasse ich erstmal komplett dem Windows-Admin ;-).
Als erstes richten wir auf der BIG-IP eine Kerberos SSO-Konfiguration ein:
Unter „SSO Configurations“ findet man auch schon die passende Option.
Was gibt es hier zu beachten?
Ich habe bei mir den KDC eingetragen, das muss nicht sein. Ist in der Praxis aber etwas schneller, da der KDC nicht erst discovered werden muss. Namen können hier natürlich auch eingesetzt werden.
Spannend ist immer der SPN Pattern. Per default, also wenn nichts eingetragen ist, wird hier HTTP/%s@REALM verwendet. Wobei das %s für den Namen des ausgewählten Backend-Server steht. Kurz zusammengefasst: Der Request trifft bei der BIG-IP ein, es wird die Authentifizierung durchgeführt und bevor der Request an den Backend-Server weitergereicht wird, muss dieser über das Balancing-Verfahren ausgewählt werden. Die IP-Adresse des Ziel-Servers wird über DNS Reverse-Lookup aufgelöst und der Name wird als SPN verwendet. Das bedeutet natürlich auch, dass für den Delegation-Account auch die entsprechenden Namen hinzugefügt werden müssen (s.o.).
Alternativ kann man auch statt mit „Host-based“ mit „Domain Account-based“ Zugriff arbeiten und würde unter dem SPN Pattern einen Eintrag der Form „http/www.example.com“ vornehmen. Natürlich muss die Konfiguration der IIS-Server auch entsprechend angepasst werden.
Als Credential Source müssen die Variablen genommen werden, in denen nachher auch die entsprechenden Informationen enthalten sind.
Kommen wir zum nächsten Schritt. Dem Anlegen einer Access-Policy:
Hier wählen wir das übliche Vorgehen. Unter Access Profiles klicken wir auf das „Plus-Zeichen“, geben der Policy einen Namen, fügen eine Sprache hinzu und vergessen nicht unter „SSO Configuration“ unser eben angelegtes Kerberos-SSO Objekt auszuwählen. Für den ersten Test sollte das reichen, Timeout-Werte etc. können später noch entsprechend angepasst werden, falls notwendig.
Öffnen wir nun der „Visual Policy Editor“ (VPE). Eine User Authentifizierung gegen das AD habe ich in einem vorigen BLOG-Beitrag schon gezeigt, daher denke ich, lassen wir den User sich diesmal mittels Client Zertifikat ausweisen.
Damit das auch funktioniert, müssen wir unserem Client-SSL-Profil noch eine Eigenschaft hinzufügen. Nämlich, dass ein Client-Zertifikat benötigt oder wie in diesem Screenshot zu sehen angefragt (request) wird. Geprüft wird es dann gegen die entsprechende CA.
Die Frage lautet nun sicher, warum ich das vorhanden sein eines validen Client Zertifikat, nicht auf „require“ gesetzt habe. Nun, da spricht nichts gegen, aber ich will die Kontrolle dessen, in der Access-Policy abfangen und genau da hin kommen wir jetzt.
In meiner Policy füge ich als erstes nun das „On-Demand-Cert-Auth“ Objekt ein. Hier muss das Client-Zertifikat nun auch vorhanden sein. Übrigens wird hier ein SSL-Rehandshake durchgeführt.
Ist das Client-Zertifikat nun valide, ist der User autorisiert, auf den Backend-Server zuzugreifen. Vorher brauchen wir aber noch ein Kerberos-Ticket für ihn. Das bedeutet aus dem Zertifikat müssen wir den Usernamen extrahieren. Dieser kann in verschiedenen Feldern des Zertifikates stehen. Mit Hilfe des „Variable Assigns“ und ein wenig TCL können wir aber ziemlich flexibel auf alles eingehen.
Fügen wir als erstes also das Objekt „Variable Assign“ in unseren „Successful“-Branch ein.
Mit Hilfe des Variable Assign können wir neue Variablen erstellen, oder bestehende verändern.
Wir erinnern uns an unsere Kerberos-SSO Konfiguration. Dort haben wir angegeben, dass der Username aus der Variablen session.logon.last.username genommen werden soll und die Domain aus session.logon.last.domain. Das bedeutet, wir müssen nun dafür sorgen, dass diese Variablen auch entsprechend gefüllt sind.
Ein Blick in die bereits existierenden Session Variablen nach einem ersten Einloggen verrät, dass in meinem Fall der Username in der Variablen session.ssl.cert.x509extension gespeichert ist und er dort nun aus der recht langen Zeile extrahiert werden muss.
Was es angenehm macht, mein Username ist in meiner Mail-Adresse enthalten und steht begrenzt von den Zeichen UPN<sven.mueller@example.com> Also kann ich die Mailadresse mit ein wenig Regular Expression schnell rausfiltern.
Zur Erklärung:
set f1 [mcget {session.ssl.cert.x509extension}] Speichert den Inhalt der Session Variablen in die temporäre Variable f1, mit der im Folgenden gearbeitet wird.
regexp {(.*)UPN<(.*)>(.*)} $f1 matched sub1 sub2 sub3 Verwende Regular Expression und speichere alles was in der ersten runden Klammer matched, in die Variable sub1. Das sind alle Zeichen (.*) bis zur Zeichenfolge „UPN<“. Alles was dann an Zeichen kommt, bis zum Zeichen „>“ (und das ist die Mailadresse) speichere in die Variable sub2. Der Rest soll in die Variable sub3 gespeichert werden.
Das Ganze soll angewendet werden, auf den Inhalt der Variablen f1, also session.ssl.cert.x509extension.
return $sub2 Weist den Inhalt der Variablen sub2 (also die Mailadresse) und die Session Variable session.logon.custom.username zu.
Soweit so gut. Nun muss der Username, also der Teil vor dem „@“ Zeichen noch extrahiert werden und der Domain Teil muss auch noch in eine Session-Variable geschrieben werden. Also fügen wir dem Variablen Assign noch zwei Einträge hinzu:
session.logon.last.username expr {[lindex [split [mcget {session.logon.custom.username}] "@"] 0]}
Hier zerlegen wir den Inhalt der Variablen session.logon.last.username in ein Array und als Trenner soll das „@“ Zeichen dienen. Somit steht im 0-ten Feld des Array unser Unsername.
session.logon.last.domain expr {[lindex [split [mcget {session.logon.custom.username}] "@"] 1]}
Im 1-ten Feld des Array steht die Domain und die weisen wir nun auch einer Session Variablen zu.
Perfekt! Schon ist alles fertig. Policy applyen, dem entsprechenden virtuellen Server zufügen und testen. J
Falls es nun doch noch nicht auf Anhieb funktioniert, so werde ich in meinem nächsten Beitrag auf das Debuggen eingehen. Bis dahin aber erstmal viel Erfolg und Spaß bei der Konfiguration.
Ihr F5-Blogger, Sven Müller
- Alexander_01_13NimbostratusHallo,
- John_MeggersNimbostratusAny chance of getting an English translation?