In diesem Beitrag beschreibe ich, wie ich FreeIPA als Zentrale zur Authentifizierung für Webanwendungen wie pfsense und proxmox und Systemdienste wie Puppet und Postfix nutze. Dazu kommen LDAP und SSL-Clientzertifikate zum Einsatz.

Bisherige Beiträge in der Reihe:

Möglichkeiten der Authentifizierung

SSL-Clientzertifikate zur Authentifizierung von Diensten

Für Dienste wie Postfix und Puppet läuft die Authentifizierung meist über SSL-Clientzertifikate. Man könnte natürlich auch Benutzername und Kennwort verwenden, die sind allerdings eher praktisch für Menschen, die sie sich merken sollen, als für Maschinen, die durchaus auch zu asymmetrischer Kryptographie mit privaten Schlüsseln und signierten Zertifikaten und so weiter fähig sind. Dabei erstellt ein Host ein Schlüsselpaar aus privatem und öffentlichem Schlüssel, mit dessen Hilfe er Dinge signiert und verschlüsselt. Anders als bei GPG ist bei SSL allerdings für gewöhnlich eine Zertifizierungsstelle im Spiel, die das Vertrauen in die Schlüssel und Zertifikate angibt. Erstellt ein Host eine Zertifikatsanfrage, wird dieses Zertifikat von einer CA signiert und als Zertifikat zurück an den Host geliefert. Der weist sich anderen Hosts gegenüber damit aus. Diese Hosts müssen im Unterschied zu GPG im Vorfeld keine Zertifikate oder Schlüssel vom ursprünglichen Host haben; sie haben vielmehr das Zertifikat der Zertifizierungsstelle (CA) als vertrauenswürdig eingestuft und sehen, dass die CA dem ursprünglichen Host bescheinigt, auch vertrauenswürdig zu sein. Dieses Verfahren eignet sich natürlich hauptsächlich bei Anwendungsfällen, bei denen das Setup strikt vorgegeben werden kann, also auf allen beteiligten Hosts auch die CA hinterlegt ist.

Bei FreeIPA ist eine CA dabei und das Aufnehmen neuer Hosts in die von FreeIPA verwaltete Domäne beinhaltet die automatische Installation des Zertifikats der CA auf dem Host, es trauen also alle Mitglieder der Domäne automatisch den durch die CA ausgestellten Zertifikaten.

Für Postfix ist die Authentifizierung durch SSL-Clientzertifikate optional. Man kann Postfix so konfigurieren, dass ein Host E-Mails verschicken darf, wenn er sich mit einem Zertifikat anmeldet, das von der FreeIPA-CA signiert wurde.

Für Puppet ist die Verwendung von Clientzertifikaten zur Authentifizierung von Nodes gegenüber dem Puppet Server sogar Standard. In seiner Ausgangskonfiguration betreibt Puppet seine eigene CA und bietet die Möglichkeit, entweder Regeln festzulegen, anhand derer die CA automatisch Clientzertifikate der Nodes signiert oder auf der Kommandozeile den Nutzer selbst die Zertifikate signieren zu lassen. Die eingebaute CA lässt sich jedoch auch deaktivieren und stattdessen ein CA-Zertifikat hinterlegen. Nodes, die sich mit einem durch diese CA signierten Zertifikat bei Puppet anmelden, werden damit authentifiziert.

Warum über die zentrale CA von FreeIPA?

Es wäre weiterhin problemlos möglich, die CA von Puppet weiterzuverwenden und, wie im Artikel zu Postfix beschrieben, die sogar für die Authentifizierung der Mailserver untereinander zu verwenden.

Man stößt so allerdings noch an ein Problem bei der Automatisierung des Aufsetzens neuer Hosts: Man muss nicht nur die Provisionierung (VM anlegen, OS-Template aufspielen, Puppet installieren) sondern auch das Signieren neuer Zertifikate auf dem Puppet Server von Hand machen. Es gibt natürlich auch die Möglichkeit, das über autosign irgendwie zu automatisieren, am sichersten ist aber die Verwendung der CA. Der Bezug der für Puppet und Postfix zu verwendenten, signierten, Zertifikate kann Teil des Provisionierungsscripts werden und so besser automatisiert werden.

Benutzer und Gruppen in Webanwendungen mit Hilfe von LDAP

Webanwendungen unterstützen als häufigste externe Authentifizierungsmöglichkeit meist LDAP. FreeIPA wird im Hintergrund auch durch LDAP gestützt und bietet daher die Möglichkeit, für Webanwendungen die Authentifizierung zu übernehmen.

Die jeweiligen Details zur Authentifizierung sind jedoch von Anwendung zu Anwendung unterschiedlich. Viele Anwendungen bieten etwa nur die Möglichkeit, Benutzer aus LDAP zu holen und implementieren die Gruppen selbst, wenn sich das von ihnen verwendete Schema nicht genau auf LDAP abbilden lässt. Manche Anwendungen brauchen weiterhin einen eigenen Account im LDAP, mit dessen Hilfe sie die Authentifizierung anderer Accounts und Einsicht in deren Details unternehmen können, anderen reicht eine anonyme Verbindung.

Login auf Systemen mit SSH-Key, Single Sign On mit Kerberos, OpenID, etc

In diesem Artikel behandle ich ledichlich die beiden oben genannten Methoden, da es mir um Authentifizierung bei Webanwendungen und von Diensten untereinander geht.

Der Login auf Linux-Systemen mit im LDAP hinterlegten SSH-Keys geht bei FreeIPA für gewöhnlich out of the box. Das ist sehr praktisch zur Authentifizierung von Nutzern bei der SSH-Anmeldung, allerdings nicht relevant für die Zielsetzungen.

Single Sign On mit Kerberos-Tickets ist unheimlich praktisch, damit man nicht überall das selbe Passwort ständig nochmal eingeben muss. Voraussetzung dafür ist bei der Anmeldung bei Webanwendungen entweder, dass der Browser sich selbst gegenüber Kerberos authentifiziert, was quasi nur geht, wenn die Workstation auch Teil der Domäne ist, oder wenn man einen Authentifizierungsproxy davorschaltet, der für einen dann die Einrichtung des Single Sign On übernimmt. Beide Methoden sind außerhalb der Reichweite dieses Artikels. Vielleicht gibt es später mal einen eigenen Artikel dazu.

Für Verwendung im großen Internet gegenüber anderen Diensten ist OpenID sehr praktisch. Es spricht nichts dagegen, einen OpenID-Provider gestützt von FreeIPA aufzusetzen, der Nutzer der Domäne auch im Internet ausweist, ohne zu viel der Infrastrktur nach außen hin zugänglich zu machen. Die Zielsetzung dieses Artikels ist jedoch die Authentifizierung innerhalb des Netzwerks, wo LDAP und SSL-Zertifikate verfügbar sind.

Externe CA für Puppet Agent, Puppet Server und PuppetDB verwenden

Damit der Austausch der internen Puppet-CA durch die zentrale von FreeIPA gelingt, muss das auf allen Komponenten gleichzeitig passieren:

Puppet Server mit externer CA betreiben

Zuallererst beenden wir alle Puppet-Dienste:

systemctl stop puppet puppetserver puppetdb

Dann wird der Dienst bei FreeIPA registriert. Dazu braucht man entweder die Konsole des FreeIPA-Servers oder eine Workstation mit installierten freeipa-admintools:

ipa service-add puppetmaster/puppet.domain.tld
ipa service-add puppetdb/puppet.domain.tld
ipa service-add puppet/puppet.domain.tld

Wir registrieren hier gleich drei Dienste: den puppetmaster-Dienst, der das Zertifikat für den Puppet Server-Daemon erhält, den puppetdb-Dienst und den puppet-Dienst, der das Clientzertifikat erhält, mit dem sich der lokale Puppet Agent authentifiziert.

puppet.domain.tld ist dabei der FQDN des Puppet Servers, also ggf. entsprechend anzupassen. Die Namen puppet und puppetmaster vor dem /puppet.domain.tld sind frei wählbar, sollten aber nachvollziehbar benannt werden.

Nun generieren wir einen privaten SSL-Schlüssel und fordern von der CA ein signiertes Zertifikat für den FQDN des Hosts an und kopieren das CA-Zertifikat

ipa-getcert request -K puppetmaster/puppet.domain.tld \
                    -k $(puppet master --configprint hostprivkey) \
                    -f $(puppet master --configprint hostcert) \
                    -N $(hostname -f)
cp /etc/ipa/ca.crt $(puppet master --configprint localcacert)

Hat alles geklappt, werden nicht nur Schlüssel und Zertifikate installiert sondern auch automatisch die Zertifikate auf ihr Ablaufen hin durch certmonger überwacht und ggf. verlängert.

Puppet DB mit externer CA betreiben

Normalerweise verwendet die Puppet DB einfach die gleichen Schlüssel und Zertifikate wie der Puppet Server, beim puppetdb ssl-setup kopiert es sich diese einfach. Das ist normalerweise in Ordnung, wir wollen aber, dass certmonger unsere Zertifikate automatisch erneuern kann. Das könnte man über Symlinks lösen, allerdings laufen puppetdb und puppet server mit unterschiedlichen UIDs und an Gruppenmitgliedschaften oder ACLs herumspielen liegt mir da nicht so. Wir machen also eigene, von der CA signierte, Zertifikate für die Puppet DB:

ipa-getcert request -K puppetdb/puppet.domain.tld \
                    -k /etc/puppetlabs/puppetdb/ssl/private.pem \
                    -f /etc/puppetlabs/puppetdb/ssl/public.pem \
                    -N $(hostname -f)
cp /etc/ipa/ca.crt /etc/puppetlabs/puppetdb/ca.pem

Puppet Agent mit externer CA betreiben

Dieser Schritt muss nicht nur auf dem Puppet Server-Host sondern natürlich auch für jeden Host mit Puppet Agent einzeln ausgeführt werden, gegebenenfalls als Teil des Provisionierungsscriptes gleich nach apt-get install puppet:

ipa-getcert request -K puppet/$(hostname -f) \
                    -k $(puppet agent --configprint hostprivkey) \
                    -f $(puppet agent --configprint hostcert) \
                    -N $(hostname -f)
cp /etc/ipa/ca.crt $(puppet agent --configprint localcacert)

Weiterhin muss noch etwas Konfiguration am Puppet Agent vorgenommen werden:

[master]
# [...]
certificate_revocation = false

[main]
# [...]
server = #hier den FQDN des Puppet Servers eintragen
ca_server = #hier auch
certname = #hier den lokalen FQDN eintragen

[agent]
certificate_revocation = false
certname = #hier den lokalen FQDN eintragen

Es ist an dieser Stelle wichtig, von der automatisch geratenen Standardeinstellung puppet als Hostname zum FQDN des Puppet Server zu wechseln, da diese Einstellung zum Common Name-Feld des Zertifikats passen muss.

Alles wieder starten

Hat man diese Schritte auf dem Puppet Server und den letzten auf jedem Host, auf dem ein Puppet Agent laufen soll durchgeführt, kann man Puppet wieder starten und die Verbindung sollte mit Absicherung durch die Clientzertifikate gelingen:

systemctl start puppetdb puppetserver puppet

Client-Zertifikate zur Authentifizierung an Postfix

Im Artikel zur Installation von Postfix als Mail-Relay habe ich ja schon beschrieben, wie die grundsätzliche Einrichtung funktioniert. Diese Anleitung lässt sich leicht modifizieren:

ipa service-add smtp/$(hostname -f)
mkdir /etc/postfix/ssl
ipa-getcert request -K smtp/$(hostname -f) \
           -k /etc/postfix/ssl/private.pem \
           -f /etc/postfix/ssl/public.pem \
           -N $(hostname -f)
cp /etc/ipa/ca.crt /etc/postfix/ssl/ca.pem
chmod 600 /etc/postfix/ssl/*pem
chmod 700 /etc/postfix/ssl

auf dem Relay ausführen und ein paar Änderungen am Puppet-Manifest profiles/manifests/mailrelay.pp vornehmen:

postfix::config {
  # [...]
  'smtpd_tls_cert_file'        : value => '/etc/postfix/ssl/public.pem';
  'smtpd_tls_key_file'         : value => '/etc/postfix/ssl/private.pem';
  'smtpd_tls_CAfile'           : value => '/etc/postfix/ssl/ca.pem';
}

Die gleichen Befehle von oben auch auf jedem Host ausführen, der Mails über das Relay verschicken soll und folgende Änderungen am Profil profiles/manifests/mail.pp vornehmen:

postfix::config {
  'smtp_tls_cert_file': value      => "/etc/postfix/ssl/public.pem";
  'smtp_tls_key_file' : value      => "/etc/postfix/ssl/private.pem";
  'smtp_tls_CAfile'   : value      => "/etc/postfix/ssl/ca.pem";
}

Auf allen hosts systemctl restart postfix ausführen und sie sollten sich jetzt anhand der SSL-Zertifikate von FreeIPA authentifizieren.

Mit LDAP bei Webanwendungen einloggen

Die Einrichtung von LDAP ist jede Webanwendung etwas unterschiedlich, wobei die Grundsätze immer die gleichen sind. Ich mache einfach mal exemplarisch die Einrichtung für pfsense und proxmox:

Proxmox mit LDAP-Authentifizierung gegen FreeIPA

proxmox mit ldap auth

Die Einstellungen zur Einrichtung von LDAP als Backend für die Authentifizierung findet man bei Proxmox unter Datacenter, dann in der mittleren Navigation unter Permissions und Authentication. Dort klickt man auf Add, LDAP-Server. Die folgenden Eingaben sind zu tätigen:

  • Realm: ipa.domain.tld oder was man halt als Realm gewählt hat bei der Installation von FreeIPA.
  • Base Domain Name: cn=users,cn=accounts,dc=ipa,dc=domain,dc=tld - die Elemente mit dc natürlich an das eigene Setup anpassen.
  • User Attribute Name: uid
  • Server: Die IP-Adresse oder den Hostname des FreeIPA-Servers
  • SSL: Natürlich!
  • Comment: frei wählbar.

Nun müssen Nutzer von Hand angelegt und denen aus FreeIPA zugeordnet werden:

proxmox-Usermapping

Die Einstellungen erklären sich von selbst; man muss eben bei Realm den eben eingerichteten FreeIPA-Zugangs auswählen und den User name entsprechend setzen. Der so neu zugeordnete Nutzer kann dann wie jeder andere Nutzer in Proxmox verwendet werden.

pfsense mit LDAP-Authentifizierung gegen FreeIPA

Bei der Verwendung von pfsense ist es notwendig, einen Benutzer im FreeIPA anzulegen, der die notwendigen Details zur Authentifizierung aus dem LDAP-Verzeichnis holen darf. Dessen Passwort soll bitte auch nicht ablaufen, da damit keine interaktiven Logins stattfinden.

Systemnutzer für LDAP-Authentifizierung anlegen

Dazu habe ich in der Weboberfläche von FreeIPA (https://auth.domain.tld) zunächst eine neue Gruppe systemaccounts angelegt und unter Regeln, Passwortregeln auf Hinzufügen geklickt und eine neue Regel für die Gruppe systemaccounts mit Priorität 10 angelegt, bei der die Max Dauer (Tage) auf 0 gesetzt ist und die Min Länge auf 10. Dann habe ich zurück unter Identität den Nutzer auth angelegt, ihm ein kompliziertes Kennwort gegeben und ihn zur Gruppe systemaccounts hinzugefügt.

CA-Zertifikat in pfsense installieren

Damit die Kommunikation über TLS mit dem FreeIPA-Host klappt, muss das Zertifikat der CA importiert werden. Dazu rufen wir die Weboberfläche von FreeIPA auf, begeben uns unter Authentifizierung zu Zertifikate und klicken dort das Zertifikat mit der Seriennummer 1 an - das Zertifikat der CA. Auf dem Knopf Aktionen findet man Download. Man erhält dann eine Datei cert.pem, die man abspeichern kann.

Damit begeben wir uns in die Weboberfläche von pfsense und dort unter System auf den Certificate Manager. Der Reiter CAs ist bereits vorausgewählt. Mit dem Knopf Add fügen wir einen neuen Eintrag hinzu und nennen den etwa FreeIPA und fügen bei Certificate Data den Inhalt der cert.pem von gerade eben ein. Die restlichen Einstellungen kann man so lassen.

Authentifzierungsserver für pfsense einrichten

Zuerst muss wieder ein Authentication Server hinzugefügt werden. Die notwendigen Menüs findet man unter System, User Manager, Authentication Servers. Durch Klick auf Add findet man den Dialog, mit dessen Hilfe man die Einstellungen vornehmen kann. Dort muss man wie folgt eintragen:

  • Descriptive Name: IPA (nach Wahl)
  • Type: LDAP
  • Hostname or IP alias: auth.domain.tld (anpassen)
  • Port value: 389
  • Transport: TCP - StartTLS
  • Peer Certificate Authority: FreeIPA
  • Protocol Version: 3 (so lassen)
  • Server Timeout: 25 (so lassen)
  • Search Scope: Entire Subtree
  • Base DN: DC=ipa,DC=domain,DC=tld
  • Authentication Containers: CN=accounts
  • Bind anonymous: Den Haken wegmachen, damit wir Zugangsdaten eingeben können
  • Bind credentials: uid=auth,cn=users,cn=accounts,dc=ipa,dc=domain,dc=tld
  • User naming attribute: uid
  • Group naming attribute: cn
  • Group member attribute: memberOf
  • Den Rest so lassen

Benutzergruppen anlegen

Nun braucht man für jede Benutzergruppe, die in pfsense verwendet werden soll, ein Pendant im LDAP, also legen wir in der Weboberfläche von FreeIPA eine neue Gruppe sysadmins an. Die Benutzer, welche pfsense verwalten können sollen, werden hier auch gleich hinzugefügt. Die gleiche Gruppe legen wir dann ebenfalls in der Weboberfläche von pfsense an - unter System, User Manager, Groups. Die Gruppe braucht hier keine Mitglieder - die kommen bei uns aus LDAP.

Die neue Gruppe bekommt auch gleich ihre Berechtigungen: Dazu klickt man auf das kleine Stift-Symbol neben ihrem Namen. Unter Assigned Privileges klicken wir auf Add und suchen uns aus, was die Gruppe können soll. Ich brauche keine vielschichtige Unterteilung der Rechte, also wähle ich WebCfg - All Pages und speichere ab.

Authentifizierung testen

Unter Diagnostics, Authentication findet man ein Formular, bei dem man IPA als Authentication Server wählen und einen Benutzer aus LDAP mit seinem Passwort eingeben kann, um zu sehen, ob die Authentifizierung klappt und welchen Gruppen der Nutzer zugeordnet ist. Ohne Gruppen kommt der Nutzer zwar in die Weboberfläche, sieht aber nur eine Fehlermeldung.