📱 Erkannter Endgerättyp ⛱️ Tag und Nacht. Verbraucht keinen oder einen 🍪.
guest
Login 🧬 0 Ihre DNS in den Krei.se-DNS-Servern, führt zum Bio-Labor 🍪 0 Anzahl Ihrer gespeicherten Kekse, führt zur Keksdose

🐕‍🦺 Kerberos mit 389DS 🫈

Server und Clients: NTP kontrollieren

/etc/systemd/timesyncd sollte denselben NTP-Server haben, am besten einen lokalen

root@linux:~# timedatectl

                  Local time: Tue 2025-01-01 02:01:01 CET
              Universal time: Tue 2025-01-01 01:01:01 UTC
                    RTC time: Tue 2025-01-01 01:01:01
                   Time zone: Europe/Berlin (CET, +0100)
   System clock synchronized: yes
                 NTP service: active
             RTC in local TZ: no

🧑‍🔧 Installation Router / DNS

DNS-SRV und -TXT Records

/etc/krb5.conf - dns_lookup_realm = true

_kerberos.domain.tld    TXT     "DOMAIN.TLD"

/etc/krb5.conf - dns_lookup_kdc = true

_kerberos._udp.domain.tld.     IN SRV 1  0 88  auth.domain.tld.
_kerberos._tcp.domain.tld.     IN SRV 1  0 88  auth.domain.tld.
_kerberos-adm._tcp.domain.tld. IN SRV 1  0 749 auth.domain.tld.
_kpasswd._tcp.domain.tld.      IN SRV 1  0 464 auth.domain.tld.

Auf dem Server checken ob kdc auf udp oder tcp lauscht. Der Client hat tryorder udp, dann tcp.

[kdcdefaults]
    kdc_ports = 750,88
    kdc_tcp_ports = 88

Debuggen: KRB5_TRACE=/dev/stdout kinit user@REALM

Wer OpenWRT hat und die TXT-Einstellungen sucht die ab 2024 auf wundersame Weise in Luci verschwunden sind: Die TXT-Records kann man in /etc/dnsmasq.conf setzen:

txt-record=_kerberos.domain.tld,"DOMAIN.TLD"

Wir brauchen diese Records zwar nicht zwingend, aber die Client-Config ist so schlanker und der Laptop z.B. auch in anderen Domänen ohne Angabe von @DOMAIN.TLD daheim.

🧑‍🔧 Installation Server

root@server:~# apt install krb5-user krb5-kdc krb5-admin-server krb5-kdc-ldap

hostname auth.domain.tld nutzen

Kerberos-Daten in 389DS 🫈 hinterlegen

Als erstes brauchen wir LDAP als Backend für 🦴 Kerberos Principals und ein paar Kerberos-Server-Einstellungen wie Ticket-Lebenszeit, etc.

schema kopieren, 60kerberos.ldif liegt in /usr/local/share/dirsrv/data --> /etc/dirsrv/slapd-ldap/schema

Indizes

dsconf INSTANCE backend index add --attr krbPrincipalName --index-type eq "dc=domain,dc=tld" dsconf INSTANCE backend index add --attr krbCanonicalName --index-type eq "dc=domain,dc=tld"

Instanz neustarten

Wir brauchen in LDAP jetzt 2 User für die Dienste kdc und kadmin (Verteiler von Tickets und Kerberos-Admin)

Wo die liegen ist zwar egal, aber ou=Dienste,dc=domain,dc=tld bietet sich natürlich an:

uid=kdc,ou=Dienste und uid=kadmin,ou=Dienste anlegen (objectClass account und simpleSecurityObject)

dn: uid=kadmin,ou=services,dc=domain,dc=tld
objectClass: account
objectClass: simpleSecurityObject
objectClass: top
uid: kadmin
description: Kerberos Admin-Server-Account

dn: uid=kdc,ou=services,dc=domain,dc=tld
objectClass: account
objectClass: simpleSecurityObject
objectClass: top
uid: kdc
description: Kerberos Key-Distribution-Center (TGT-Server)

kann man in Cockpit machen, bissel hakelig aber geht.

👮 ACIs

# 1. Provide the KDC permission to read everything and write lockout data
dn: dc=domain,dc=tld
changetype: modify
add: aci
aci: (targetattr="*")(version 3.0; acl "KDC Read Access"; allow (read,search,compare) userdn="ldap:///uid=kdc,ou=services,dc=domain,dc=tld";)
-
add: aci
aci: (targetattr="krbLastSuccessfulAuth || krbLastFailedAuth || krbLoginFailedCount || krbLastAdminUnlock")(version 3.0; acl "KDC Write Access for Lockouts"; allow (write) userdn="ldap:///uid=kdc,ou=services,dc=domain,dc=tld";)

# 2. Provide Kadmin full access to the whole suffix (to manage keys/principals)
dn: dc=domain,dc=tld
changetype: modify
add: aci
aci: (targetattr="*")(version 3.0; acl "Kadmin Full Access"; allow (all) userdn="ldap:///uid=kadmin,ou=services,dc=domain,dc=tld";)

# 3. Deny everyone else from seeing the actual keys (The Security Layer)
dn: dc=domain,dc=tld
changetype: modify
add: aci
aci: (targetattr="krbPrincipalKey || krbExtraData")(version 3.0; acl "Restrict Kerberos Keys"; deny (read,search,compare) userdn!="ldap:///uid=kdc,ou=services,dc=domain,dc=tld" AND userdn!="ldap:///uid=kadmin,ou=services,dc=domain,dc=tld" AND userdn!="ldap:///cn=Directory Manager";)

Kann man in Cockpit manuell adden.

Für Kerberos ist wichtig, dass wir allen DNs die einen krbPrincipalKey haben (also ein Passwort) ähnliche Rechte wie für userPassword geben und beiden uid=kdc und uid=kadmin ähnliche Rechte wie anderen lookup- oder users-Diensten die Nutzerdaten selektiv lesen /schreiben können.

Kerberos Server: 🫈 LDAP-Backend einstellen

https://wiki.debian.org/LDAP/OpenLDAPSetup#Kerberos

/etc/krb5kdc/kdc.conf

[kdcdefaults]
    # 750 is kerb4 compatibility port, can be left like this!!
    kdc_ports = 750,88
    # Wer mit TCP noch extra lauschen will, aber dran denken tryorder ist udp, tcp
    kdc_tcp_ports = 88

[realms]
    DOMAIN.TLD = {
        # das ist nur der name, hat nix zwingend mit openldap zu tun
        database_module = ds_backend
        database_name = /var/lib/krb5kdc/principal
        admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
        acl_file = /etc/krb5kdc/kadm5.acl
        key_stash_file = /etc/krb5kdc/stash
        kdc_ports = 750,88
#       Wird in LDAP überschrieben
#        max_life = 24h 0m 0s
        # means you can get a new ticket with the old one
#        max_renewable_life = 7d 0h 0m 0s

        #master_key_type = aes256-cts
        #supported_enctypes = aes256-cts:normal aes128-cts:normal
#       default_principal_flags = +preauth
    }

[dbmodules]
        ds_backend = {
                db_library = kldap

                #ldap_kerberos_container_dn = cn=krbContainer,ou=kerberos,ou=Services,dc=domain,dc=tld
                ldap_kerberos_container_dn = cn=krbContainer,ou=Dienste,dc=domain,dc=tld

                # if either of these is false, then the ldap_kdc_dn needs to
                # have write access as explained above
                disable_last_success = true
                disable_lockout = true
                ldap_conns_per_server = 5
                ldap_servers = ldaps://ldap.domain.tld/

                # this object needs to have read rights on
                # the realm container, principal container and realm sub-trees
                #ldap_kdc_dn = "uid=kdc,ou=kerberos,ou=Services,dc=domain,dc=tld"
                ldap_kdc_dn = "uid=kdc,ou=Dienste,dc=domain,dc=tld

                # this object needs to have read and write rights on
                # the realm container, principal container and realm sub-trees
                #ldap_kadmind_dn = "uid=kadmin,ou=kerberos,ou=Services,dc=domain,dc=tld"
                ldap_kadmind_dn = "uid=kadmin,ou=Dienste,dc=domain,dc=tld"

                # this file will be used to store plaintext passwords used
                # to connect to the LDAP server
                ldap_service_password_file = /etc/krb5kdc/service.keyfile

                # OR, comment out ldap_kdc_dn, ldap_kadmind_dn and
                # ldap_service_password_file above and enable the following
                # two lines, if you skipped the step of creating entries/users
                # for the Kerberos servers

                #ldap_kdc_sasl_mech = EXTERNAL
                #ldap_kadmind_sasl_mech = EXTERNAL
                #ldap_servers = ldapi:///
        }

Jetzt nutzen wir das coole kdb5_ldap_util um den Kerberos-Container in LDAP anzulegen und für die beiden Dienst-DNs die Passwörter in /etc/krb5/service.keyfile zu speichern.

ldap-sachen anlegen:

#neues DB-Master passwort setzen, cn=krbContainer,ou=Dienste,dc=domain,dc=tld anlegen

root@auth:~# kdb5_ldap_util -D "cn=Directory Manager" create -subtrees dc=domain,dc=tld -r DOMAIN.TLD -s -H ldaps://ldap.domain.tld/

Jetzt die Passwörter für uid=kdc und uid=kadmin hinterlegen die Kerberbos braucht um sich zu LDAP zu verBinden

root@auth:~# kdb5_ldap_util -D "cn=Directory Manager" stashsrvpw -f /etc/krb5kdc/service.keyfile uid=kdc,ou=services,dc=domain,dc=tld
root@auth:~# kdb5_ldap_util -D "cn=Directory Manager" stashsrvpw -f /etc/krb5kdc/service.keyfile uid=kadmin,ou=services,dc=domain,dc=tld

🧑‍💻 Benutzer-Passwörter durch Kerberos

Hier gibts 2 Konzepte zu beachten:

- Entweder ich binde an den LDAP mit einem DN, also uid=user,ou=people,dc=domain,dc=tld

- ODER ich hab schon ein Kerberos Prinzipal

Im ersten Fall checken wir das PAM Pass-Through Plugin ob der Zweig mit dem im LDAP gespeicherten userPassword einloggt oder Kerberos gefragt wird.

Hier haben wir oft service accounts mit Passwort direkt in LDAP oder Kerberized Benutzer mit einem eigenen Principal - für die fragen wir dann nochmal Kerberos ab.

read up on https://docs.redhat.com/en/documentation/red_hat_directory_server/11/html/administration_guide/sasl

Wir wollen KEIN Fallback und die host/ Prinzipals zuerst mappen, dann alle @REALM ohne host/ oder service/ für die user principals mit einer etwas höheren (also niedrigeren ...) Prio

root@auth:~# apt install libpam-krb5

Mapping in Cockpit -> SASL Settings adden:

name    machine mapper
regexp  ^host/\([^.]*\)\..*domain\.tld$
base    ou=machines,dc=domain,dc=tld
filter  (&(objectClass=device)(cn=\1))
prio    10

name    user mapper
regexp  ^[^/@]+$
base    ou=people,dc=domain,dc=tld
filter  (&(objectClass=posixAccount)(uid=\1))
prio    20

Plugin kann man in Cockpit anschalten.

https://docs.redhat.com/en/documentation/red_hat_directory_server/11/html/administration_guide/pam-pta

Config kann man in Cockpit hinzufügen:

"Domain.tld PTA"
include suffix dc=domain,dc=tld # das darf kein Zweig sein, kompletter DSE!
missing suffix ALLOW # wenn kein Suffix catcht trotzdem erlauben, ich weiss nicht was das soll, evtl. nur für den parent nötig.
id-attr uid # braucht man nur für Map Method Entry
Map Method RDN
filter (objectClass=posixAccount) # nur echte PosixAccounts weiterleiten, stellt sicher dass man noch uid=kdc und andere Services nicht mappt
Service ldapserver

das exclude brauchen wir weil da kdc und kadmin mit normalem userpass liegen

Service ist ldapserver und das zeigt dann auf /etc/pam.d/ldapserver

Parent PAM-PTA abschalten

Achtung das ist super nervig, wer in Cockpit Sachen hinzufügt es gibt noch einen unsichtbaren Parent Eintrag. Direkt in dse.ldif ändern:

dn: cn=PAM Pass Through Auth,cn=plugins,cn=config
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
# objectClass: pamConfig
cn: PAM Pass Through Auth
nsslapd-pluginPath: libpam-passthru-plugin
nsslapd-pluginInitfunc: pam_passthruauth_init
nsslapd-pluginType: betxnpreoperation
nsslapd-pluginEnabled: on
nsslapd-pluginloadglobal: true
nsslapd-plugin-depends-on-type: database
# pamMissingSuffix: ALLOW
# pamExcludeSuffix: cn=config
# pamIDMapMethod: RDN
# pamIDAttr: notUsedWithRDNMethod
# pamFallback: FALSE
# pamSecure: FALSE
# pamService: ldapserver
nsslapd-pluginId: pam_passthruauth
nsslapd-pluginVersion: 3.1.2
nsslapd-pluginVendor: 389 Project
nsslapd-pluginDescription: PAM pass through authentication plugin
numSubordinates: 1

Der Parent sollte noch rausfilter nur auf PosixAccounts zu antworten sonst catcht er kdc und kadmin uids

pamFilter: (&(objectClass=posixAccount)(!(uid=kdc))(!(uid=kadmin)))

Debugging SASL Mapping:

root@auth:~# dsconf INSTANCE logging error set level trace acl

das setzt 1 und 128 -> dsconf ldap config get nsslapd-errorlog-level ist dann 129

Mehr infos: https://krei.se/Doc/domain/500-389ds -> Troubleshooting

errors erscheinen in /var/log/dirsrv/slapd-INSTANCE/errors

Prinzipal holen host

root@client(!!):~# kinit -k -t /etc/krb5.keytab host/client1.domain.tld@DOMAIN.TLD

Oder halt für den User

root@client(!!):~# kinit user@DOMAIN.TLD

Dann gegen LDAP whoami schicken:

ldapwhoami -H ldap://auth.domain.tld -Y GSSAPI

/var/log/dirsrv/slapd-INSTANCE/errors zeigt jetzt welche Mappings er ausprobiert

Am Ende aufräumen:

root@auth:~# dsconf INSTANCE logging error set level default
Übliche Probleme:

Sometimes, the realm name is not included in the principal name in SASL GSS-API configuration. A second mapping can be created which is identical to the first, only without specifying the realm in the principal name.

William Brown on the issue: https://lists.fedoraproject.org/archives/list/389-users@lists.fedoraproject.org/thread/GLFBGAWI4XOBCMXL6F3KQWXV5QLBWVNL/

create 2 rules that just work

pam permit

pam findet jetzt den user nicht (getpwnam) obwohl kerberos sagt dass er ok ist. /etc/pam.d/ldapserver erstellen

# /etc/pam.d/ldapserver
# 1. Verify the password via Kerberos
auth    required    pam_krb5.so minimum_uid=1000 ccache=FILE:/var/lib/gssproxy/clients/krb5cc_%u

# 2. Always succeed the "account" check 
# This bypasses the need for the user to be in /etc/passwd
account required    pam_permit.so

Voila.

Ticket-Lifetime und Renewable erhöhen

Auch wenn Du müde bist, in cn=DOMAIN.TLD,cn=krbContainer,ou=Dienste,dc=domain,dc=tld

unbedingt noch krbMaxRenewableAge auf 604800 setzen und krbMaxTicketLife auf 86400, diese Werte auch in sssd.conf für Clienten eintragen.

🦴 Dienst-Prinzipal für 389DS 🫈 erstellen

Wofür brauch ich das? Damit Du vom LDAP aus Kerberos anfragen kannst

kadmin.local starten, neues principal für den ldap-server erstellen:

kadmin.local
addprinc -randkey ldap/ldapserverhostname.domain.tld
ktadd -k /etc/dirsrv/slapd-INSTANCE/ds.keytab ldap/ldapserverhostname.domain.tld
q

chmod 600 /etc/dirsrv/slapd-INSTANCE/ds.keytab

Diesen key noch in /etc/default/dirsrv-INSTANCE exportieren:

KRB5_KTNAME=/etc/dirsrv/slapd-INSTANCE/ds.keytab
export KRB5_KTNAME

KDC ACL

Jetzt an die kdc acls denken. Die sind standardmässig unter /etc/krb5kdc/kadm5.acl

/etc/krb5kdc/kadm5.acl

*/admin@DOMAIN.TLD        *

kadmin/admin ist der einzige Principal der in der Kerboros-Datebank alles darf. Wenn Du das wieder vergisst: Das legt NICHT fest welcher Principal welchen Service nutzen darf.

/admin Principals

kadmin.local -q "addprinc user/admin"

Die sollte man unbedingt nutzen denn kadmin/admin hat nur einen key, kein passwort.

Nutzer anlegen mit LDAP-Verbindung

Prinzipal anlegen was auf einen DN zeigt: (also ein User)

kadmin.local -q "addprinc -x dn=uid=domainUserN,ou=people,dc=domain,dc=tld domainUserN"

dessen passwort ändern ist dann ganz normal ...

kadmin.local -q "cpw domainUserN

MemberOf

Erlaubt einen schnelleren Lookup vom User zu seinen Gruppen.

member= in Gruppe hinzugefügt -> Plugin schreibt memberOf=gruppe in den User. O(1) lookups

Für den Anfang reicht aus dc=domain,dc=tld als subtree einzutragen und start zu drücken.

👷👷👷 Mal checken ob man die auto object class add braucht, bei mir gings auch so

ldap service principals

Die braucht man damit man auf dem Server SSSD laufen lassen kann ohne mit einem userprincipal oder host principal zu arbeiten. Das Principal muss nur in der DB vorliegen.

kadmin.local -q "addprinc -randkey ldap/auth.domain.tld@DOMAIN.TLD"

SystemD-Startup ergänzen

An dieser Stelle macht es Sinn Kerberos erst nach OpenLDAP starten zu lassen, bzw. auf dessen Verfügbarkeit zu warten:

root@server:~# systemctl edit krb5-kdc

erstellt eine Datei /etc/systemd/system/krb5-kdc.service.d/override.conf, wir tragen ein:

[Unit]
After=dirsrv@INSTANCE.service network-online.target
Requires=dirsrv@INSTANCE.service network-online.target

# If LDAP stops or restarts, the KDC MUST also stop or restart
BindsTo=dirsrv@ldap.service
PartOf=dirsrv@ldap.service

[Service]
Restart=on-failure
RestartSec=5

Das gleiche für

root@server:~# systemctl edit krb5-admin-server    

erstellt eine Datei /etc/systemd/system/krb5-admin-server.service.d/override.conf, wir tragen ein:

[Unit]
After=dirsrv@INSTANCE.service network-online.target
Requires=dirsrv@INSTANCE.service network-online.target

[Service]
Restart=on-failure
RestartSec=5

Kleiner Hinweis, hier sowohl After= als auch Requires= zu nutzen sorgt dafür, dass zwingend auf den erfolgreichen Start von 389DS gewartet wird und nicht nur die Startreihenfolge (After=) bzw. die Abhängigkeit (Requires=).

Ausserdem nutzen wir als Safeguard in beiden Fällen bei Fehlern den Dienst neuzustarten. Es sollte Requires= genügen aber ich würde argumentieren hier ist es ok ein bisschen zu tricksen, denn ob der Dienst neustarten musste sieht man im Log, aber immerhin geht er dann noch.

Known Bug need to restart kdc after ldap restart

https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=278395

Das ist alles für Auth von Kerberos zu LDAP

cn=config SASL stuff for GSSAPI:

If you configure the olcSaslRealm then it will be inserted as an extra component in the authorization DN, regardless of any Kerberos realms in use. For domain, if you set olcSaslRealm to domain.tld then you will get:

das brauchen wir also nicht zwingend, auch olcSaslHost scheint entweder ignoriert zu werden oder ist mit localhost gut dran.

NFS

Current PTF

Hintergrund ändern. Verbraucht keinen oder einen 🍪.

Verknüpften Viewport öffnen

🎮 Steuerung
Dokumentation 🕹️
Sie sind leider kein Entwickler :(

Content Nodes Amount

Diligence / PTF Amount

FPS

Vertex-Count