Zum Inhalt springen

authnd, ein LDAP-Server für Personen, die anderswo verwaltet werden

Ein LDAP-Verzeichnis und optional ein Kerberos-Realm über Personen aus einer Konfigurationsdatei, einer SQL-Datenbank oder einem anderen Verzeichnis.

Die Personen eines Standorts stehen bereits in einer Datenbank, einer Datei oder einem anderen Verzeichnis. Was sie authentifizieren will, spricht LDAP. authnd ist die Fassade davor: Es führt Binds und Suchen über die Quellen von go-authn/directory aus, sodass das, was eine Datenbank enthält, von allem gelesen werden kann, das ein Verzeichnis zu fragen weiß. Reines Go, CGO_ENABLED=0, ein Binary. Diese Seiten beschreiben v0.11.1, dessen Einträge den Standardschemata folgen und das Schema bestehen, das es unter cn=Subschema bereitstellt, mit go-authn/ldap v0.8.0 und go-authn/directory v0.14.0 darunter; was geprüft ist und was nicht, steht auf der Seite Stand.

Upgrade von v0.10.x

  • publish_nt_hash = true braucht nun einen samba-Block, sonst startet authnd nicht.
  • Eine Person ohne uidNumber, gidNumber und homeDirectory ist kein posixAccount mehr, und eine Gruppe ohne gidNumber keine posixGroup mehr; ein Konsument, der nach diesen Klassen filtert, sieht daher weniger Einträge: siehe die Einträge.
  • Ein users "ldap"-Block liest standardmäßig mehr aus dem Verzeichnis dahinter: siehe Personen.

authnd check mit dem neuen Binary sagt alle drei vor dem Neustart.

authnd --config /etc/authnd      # serve
authnd check /etc/authnd         # say what would be served, without listening

Die kleinste Konfiguration

listen  = "127.0.0.1:3893"            # the default
base_dn = "dc=example,dc=org"         # required

reader "cn=reader,dc=example,dc=org" { password_file = "/etc/authnd/reader.pw" }

user "alice" { password_file = "/etc/authnd/passwords/alice.pw" }

group "staff" { members = ["alice"] }

Personen werden als uid=<name>,ou=people,<base_dn> veröffentlicht, Gruppen als cn=<name>,ou=groups,<base_dn>. Was jeder Eintrag ist, ergibt sich aus dem, was seine Quelle geliefert hat: Eine Person ist ein account, oder ein inetOrgPerson, wenn es ein sn gibt, und ein posixAccount nur mit uidNumber, gidNumber und homeDirectory; jede Person ist ein uidObject. Eine Gruppe ist eine posixGroup (mit memberUid), wenn sie eine gidNumber hat, andernfalls eine groupOfNames (mit member-DNs), oder eine organizationalRole, wenn sie zudem leer ist. sshPublicKey kommt hinzu, wenn die Person Schlüssel hat, und sambaNTPassword, wenn publish_nt_hash es vorsieht und eine SID angegeben werden kann. Jeder Eintrag besteht das unter cn=Subschema bereitgestellte Schema, bevor er veröffentlicht wird: siehe die Einträge und das Schema. Bis v0.10.2 war jede Person ein posixAccount und jede Gruppe eine posixGroup, was auch immer sie hatten.

--config (-c) nimmt eine Datei oder ein Verzeichnis und darf wiederholt werden; ein Verzeichnis steht für jede .hcl-Datei darin, in Namensreihenfolge gelesen und zu einer Konfiguration zusammengeführt. Eine Konfiguration ohne base_dn oder ohne eine einzige Person startet nicht.

Wer sich binden und wer lesen darf

Ein LDAP-Server soll Personen nachweisen, also sind seine Ablehnungen das eigentliche Design. Dies sind Antworten des Release-Binarys v0.10.0 an den Client von OpenLDAP selbst:

$ ldapwhoami -x -H ldap://127.0.0.1:3893 -D uid=alice,ou=people,dc=example,dc=org -y alice.pwin
dn:uid=alice,ou=people,dc=example,dc=org

$ ldapwhoami -x -H ldap://127.0.0.1:3893 -D uid=alice,ou=people,dc=example,dc=org -y wrong.pwin
ldap_bind: Invalid credentials (49)

$ ldapwhoami -x -H ldap://127.0.0.1:3893 -D uid=alice,ou=people,dc=example,dc=org -w ''
ldap_bind: Server is unwilling to perform (53)
	additional info: an unauthenticated bind proves nothing, and this server does not accept one

$ ldapsearch -x -LLL -H ldap://127.0.0.1:3893 -D uid=alice,ou=people,dc=example,dc=org -y alice.pwin -b dc=example,dc=org '(uid=alice)'
Insufficient access (50)
Additional information: only a reader may search
AnfrageAntwortwarum
leerer Name, leeres Passwort (RFC 4513 §5.1.1, anonym)Erfolgsie sagt „ich bin niemand“, was stimmt, und ein Client sendet sie, bevor er irgendetwas herausgefunden hat
ein Name und ein leeres Passwort (§5.1.2, nicht authentifiziert)unwillingToPerformsie benennt jemanden und beweist nichts; §5.1.2 verlangt genau diesen Code. invalidCredentials würde einer Person sagen, ihr Passwort sei falsch
ein falsches Passwort oder ein Name, den hier niemand hatinvalidCredentialsbeides wird nicht unterschieden
eine Suche durch jemand anderen als einen readerinsufficientAccessRightsein Bind beweist, wer Sie sind; alle lesen zu dürfen, ist eine eigene Erlaubnis
add, delete, modifyDNunwillingToPerformdafür ist kein Handler angebunden; der eine Schreibvorgang ist das eigene Passwort einer Person

Ein reader ist ein Dienstkonto mit einem Bind-DN und password oder password_file; ein Reader ohne beides wird beim Start abgelehnt (ein Reader, der nichts beweist, ist eine anonyme Suche mit zusätzlichen Schritten). Ohne jeden Reader darf nichts suchen, und check sagt das.

Das Root-DSE wird einem anonymen Client beantwortet, wie es die Erkennung braucht:

$ ldapsearch -x -LLL -H ldap://127.0.0.1:3893 -s base -b '' '+' '*'
dn:
objectClass: top
objectClass: OpenLDAProotDSE
supportedLDAPVersion: 3
namingContexts: dc=example,dc=org
supportedExtension: 1.3.6.1.4.1.4203.1.11.3
supportedExtension: 1.3.6.1.4.1.4203.1.11.1
supportedControl: 1.2.840.113556.1.4.319
supportedControl: 1.3.6.1.1.13.1
supportedControl: 1.3.6.1.1.13.2
supportedFeatures: 1.3.6.1.4.1.4203.1.5.1
supportedFeatures: 1.3.6.1.4.1.4203.1.5.3
subschemaSubentry: cn=Subschema
vendorName: go-authn/authnd
vendorVersion: v0.11.1

1.3.6.1.4.1.4203.1.11.1 ist die Password-Modify-Operation aus RFC 3062. subschemaSubentry benennt das Schema, das ebenfalls einem anonymen Client beantwortet wird. supportedSASLMechanisms: OAUTHBEARER erscheint nur mit einem oidc-Block.

Wie es weitergeht

Installationdas Release-Binary, das Konto authnd, die systemd-Unit, Upgrades
Woher die Personen kommenuser- und group-Blöcke, eine SQL-Datenbank, ein anderes LDAP-Verzeichnis
Die Einträge und das Schemaals was jede Person und jede Gruppe veröffentlicht wird, cn=Subschema, Attribute, was weggelassen oder zurückgehalten wird
checkdie Konfiguration vor einem Neustart zurücklesen
TLSldaps:// oder StartTLS, und publish_nt_hash
Ein Passwort ändernldappasswd, ldapmodify, und warum immer nach dem alten Passwort gefragt wird
Ein Kerberos-Realmder Keytab, und wem ein Ticket ausgestellt werden kann
Ein zweiter Faktorein Einmalcode am Ende des Passworts
Ein Token beim BindOIDC über SASL OAUTHBEARER
BetriebSignale, Neustarts, was es protokolliert, woran man erkennt, dass es läuft

Zu den Transkripten

Jede Startzeile, das Root-DSE und die --version-Zeilen wurden vom Release-Binary v0.11.1 ausgegeben (authnd-darwin-arm64, go version -m: mod github.com/go-authn/authnd v0.11.1, vcs.modified=false), ebenso jeder andere Befehl, der im selben Transkript wie eine Startzeile steht. v0.11.1 ändert nichts außer dieser Zeile. Jede check-Tabelle, die mit ldapsearch zurückgelesenen Einträge, cn=Subschema und die samba-Ablehnungen wurden vom Release-Binary v0.11.0 ausgegeben (mod github.com/go-authn/authnd v0.11.0, vcs.modified=false). Ebenso die Konfigurationsablehnungen auf diesen Seiten, die v0.11.0 byte für byte so ausgab wie v0.10.0. Die übrigen Binds, kinits, Passwortänderungen und Token-Austausche wurden vom Release-Binary v0.10.0 ausgegeben und nicht erneut ausgeführt, da weder die Release-Notes von v0.11.0 noch die von v0.11.1 einen davon ändern. Alle wurden von den OpenLDAP- und Heimdal-Clients gestellt, die mit macOS ausgeliefert werden, auf 127.0.0.1 an nicht privilegierten Ports, in einem Arbeitsverzeichnis unter /tmp. Deshalb nennen die zugrunde liegenden Konfigurationen Dateien über relative Pfade wie etc/authnd/passwords/alice.pw, und deshalb haben die Passwortdateien Namen wie alice.pwin. Die Pfade unter /etc/authnd in den Beispielen sind die, die ein installierter Server verwendet.

Erstellt am von tannevaled

Geändert am von tannevaled