Wer schon einmal eine Anfrage an das FreeIPA-Framework gestellt hat, der wird wissen, dass die allermeisten Aktionen nur dann erfolgreich sind, wenn vor dem Zugriff eine erfolgreiche Authentifizierung stattgefunden hat. Diese kann entweder mittels Kerberos oder eines Passwortes erfolgen. Hierbei spielt es erst einmal keine Rolle, ob die Authentifizierung über das Webinterface oder mittels des Kommandozeilen-Tools ipa geschieht. Die Javascript-basierte Webapplikation wird beim Zugriff innerhalb des aufrufenden Browsers ausgeführt, und sämtliche Anweisungen für das Framework finden schließlich innerhalb einer gesicherten HTTPS-Verbindung mittels JSON-RPC statt. Das Tool ipa nutzt die Python-API des Frameworks, um den Zugriff zu abstrahieren. Wer diese API verwenden möchte, muss das Paket free-ipa-python (ipa-python) installieren, um in seinen Skripten das Modul ipalib importieren zu können.
Die direkte Abfrage des Frameworks über die JSON-RPC-API ist gerade dann sinnvoll, wenn der Zugriff von einem System erfolgt, das nicht Teil der FreeIPA-Domäne ist. Das ist beispielsweise der Fall, wenn Daten des Servers von einem anderen Webtool ausgelesen oder manipuliert werden sollen. Eine Abfrage besteht immer aus der gewünschten Methode, gefolgt von einem Array aus Argumenten und Optionen. Die Methodennamen der JSON-RPC API sind dabei identisch mit denen der Python-API. So existiert beispielsweise ein FreeIPA-Plug-in "User", das verschiedene Klassen zur Verwaltung von Benutzern zur Verfügung stellt. Die einzelnen Klassen-Namen sind dabei identisch mit den Argumenten, die dem ipa-Tool zu übergeben sind. So lautet die Anweisung zum Anlegen eines neuen Benutzers etwa »ipa user-add
«
, die entsprechende Klasse in der Python-API heißt daher user_add. Und dies ist eben auch der Name der Methode, die beim Zugriff auf die JSON-RPC Schnittstelle zu verwenden ist.
Seit der FreeIPA-Version 4.2 existiert innerhalb des grafischen Webinterfaces ein API-Browser, der die einzelnen Methoden beschreibt. Ansonsten ist es auch möglich, das Tool ipa im verbose-Mode aufzurufen (Option "-vv"). Die Ausgabe zeigt die verwendete Methode zusammen mit den Parametern entsprechend an (Listing 1).
Listing 1: Aufruf von ipa im verbose Mode
# ipa -vv user-add --first foo --last bar foobar [...] ipa: INFO: Forwarding 'user_add' to json server 'https://ipa01.example.com/ipa/session/json' ipa: INFO: Request: { "id": 0, "method": "user_add", "params": [ [ "foobar" ], { "all": false, "cn": "foo bar", "displayname": "foo bar", "gecos": "foo bar", "givenname": "foo", "initials": "fb", "krbprincipalname": "foobar@EXAMPLE.COM", "no_members": false, "noprivate": false, "random": false, "raw": false, "sn": "bar", "version": "2.156" } ] } [...]
Um den Benutzer mit einem direkten Zugriff auf die JSON-RPC API anlegen zu können, sind die Aufrufe in entsprechende HTTPS-Anfragen umzuwandeln. Beispielhaft kommt in diesem Open
Source-Tipp der Kommandozeilenbrowser curl zum Einsatz. Bevor es an die Entwicklung eines entsprechenden Skripts geht, ist zu bedenken, dass FreeIPA zwei unterschiedliche Einstiegspunkte zur Authentifizierung eines Benutzers zur Verfügung stellt. Somit ist es möglich, einen Benutzer mittels eines Kerberos-Tickets oder eines einfachen Passwortes anzumelden. Die beiden Einstiegspunkte lauten entsprechend "https://$IPAHOSTNAME/ipa/session/login_kerberos" respekti- ve "https://$IPAHOSTNAME/ipa/session/login_password".
Desweiteren ist zu bedenken, dass die Authentifizierung eines Benutzers im Vorfeld stattfindet und der Server ein Session-Cookie zur Verfügung stellt, das während des Aufrufs der gewünschten Methode zum Einsatz kommt. Außerdem verlangt FreeIPA einen HTTP-Referrer, der auf den IPA-Server selbst verweist. Somit wird Cross-site Request Forgery (XCRF/CSRF) Angriffen vorgebeugt.
Damit der Zugriff über einen sicheren HTTPS-Kanal funktioniert, ist das CA-Zertifikat des FreeIPA-Systems bereitzustellen. Desweiteren wird auch eine Kerberos-Konfigurationsdatei benötigt, damit der Client einen Benutzer mittels eines Kerberos-Tickets authentifizieren kann. Im einfachsten Fall wird diese Datei einfach von einem FreeIPA-System kopiert. Um nicht mit einer anderen Kerberos-Konfiguration zu kollidieren, wird ein alternativer Dateiname gewählt, der dem System dann über die Umgebungsvariable KRB5_CONFIG mitgeteilt wird.
Das Beispiel-Skript aus Listing 2 setzt all diese Anforderungen um. Das Skript soll einen neuen Benutzer mittels einer direkten Anfrage an die JSON-RPC-API des Identity-Management Frameworks anlegen. Der Benutzer muss sich beim ersten Aufruf authentifizieren. Dies gelingt entweder mittels Kerberos oder eines regulären Benutzer-Passworts. Im ersten Fall wird über kinit ein entsprechendes TGT vom Kerberos-Server des IdM-Systems angefordert, das später dazu dient, ein entsprechendes Service-Ticket für das IPA-System anzufordern. Im letzteren Fall findet eine einfache Formular-basierte Anmeldung statt. Der eingegebene Benutzername und das Passwort werden mittels einer POST-Anweisung auf den Server übertragen. Hat die Anmeldung geklappt, dient ein Cookie beim Aufruf der user_add-Methode zur Autorisierung.
Listing 2: Anlegen eines neuen Benutzers per API
#!/bin/sh export COOKIEJAR=/tmp/ipa-$$ export IPAHOSTNAME=ipa01.example.com if [ $# -ne 1 ]; then echo -e "Bitte krb oder pass als Argument angeben." && exit 1 fi # Die Authentifizierung des Benutzers, falls noch kein Cookie existiert. if [ ! -f $COOKIEJAR ] ; then if [ $1 = "krb" ] ; then export KRB5_CONFIG=/etc/krb5-ipa.conf kinit admin curl -v \ -H referer:https://$IPAHOSTNAME/ipa \ -c $COOKIEJAR -b $COOKIEJAR \ --cacert /etc/ipa/ca.crt \ --negotiate -u : \ -X POST \ https://$IPAHOSTNAME/ipa/session/login_kerberos else read -p "Bitte Benutzernamen eingeben: " username read -s -p "Bitte Passwort eingeben: " password curl -v \ -H referer:https://$IPAHOSTNAME/ipa \ -H "Content-Type:application/ x-www-form-urlencoded" \ -H "Accept:text/plain"\ -c $COOKIEJAR -b $COOKIEJAR \ --cacert /etc/ipa/ca.crt \ --data "user=$username&password=$password" \ -X POST \ https://$IPAHOSTNAME/ipa/session/login_password fi fi # Aufruf der eigentlichen Methode curl -v \ -H referer:https://$IPAHOSTNAME/ipa \ -H "Content-Type:application/json" \ -H "Accept:applicaton/json" \ -c $COOKIEJAR -b $COOKIEJAR \ --cacert /etc/ipa/ca.crt \ -d ' {"method":"user_add","params":[["foobar"],{ "cn": "foo bar", "displayname": "foo bar", "gecos": "foo bar", "givenname": "foo", "initials": "fb", "krbprincipalname": "foobar@EXAMPLE.COM", "no_members": false, "noprivate": false, "random": false, "raw": false, "sn": "bar" }],"id":0}'\ -X POST \ https://$IPAHOSTNAME/ipa/session/json
Zur Speicherung der Authentifizierungsinformationen kommen Cookies zum Einsatz, die curl in einer Datei speichert. Hinter dem Schalter "-b" erwartet curl eine Cookie-Datei, die es für einen Request verwendet, hinter "-c" folgt ein File, in das curl die vom Server gelieferten Cookies speichert. Hier wird beide Male die gleiche Datei "/tmp/ipa-$$" verwendet, wobei die Zeichen "$$" im Shellskript für die aktuelle Prozess-ID stehen.