# SSSD Connection Setup für Ubuntu, Active Directory und Proxmox LXC Dieses Repository enthält ein Bash-Skript zur automatisierten Anbindung von Ubuntu-Systemen an eine Active-Directory-Domäne über `realmd`, `adcli`, Kerberos und SSSD. Das Skript ist für klassische VMs ebenso vorgesehen wie für unprivilegierte Proxmox-LXC-Container. ## Inhaltsverzeichnis - [Zweck des Skripts](#zweck-des-skripts) - [Kurzbeschreibung des Ablaufs](#kurzbeschreibung-des-ablaufs) - [Dialoge, Fallbacks und interaktive Eingaben](#dialoge-fallbacks-und-interaktive-eingaben) - [Parameter und Umgebungsvariablen](#parameter-und-umgebungsvariablen) - [Beispielaufrufe](#beispielaufrufe) - [Technischer Ablauf im Detail](#technischer-ablauf-im-detail) - [Besonderheiten bei Proxmox LXC](#besonderheiten-bei-proxmox-lxc) - [SSSD-ID-Mapping und Container-Namespace](#sssd-id-mapping-und-container-namespace) - [Sudo-Berechtigungen über AD-Gruppen](#sudo-berechtigungen-über-ad-gruppen) - [Validierung nach dem Lauf](#validierung-nach-dem-lauf) - [Bemerkungen und TODOs](#bemerkungen-und-todos) ## Zweck des Skripts Das Skript bindet ein Ubuntu-System automatisiert an eine Active-Directory-Domäne an und richtet die dafür benötigten Komponenten ein. Es übernimmt insbesondere: - Installation der benötigten Pakete - DNS-basierte Erkennung von Domain Controllern - DNS-basierte Erkennung von Nameservern - Kerberos-Grundkonfiguration - AD-Join über `realmd` / `adcli` - SSSD-Konfiguration mit AD-Provider - automatische Home-Verzeichnisse über `pam_mkhomedir` - optionale Sudo-Berechtigungen für AD-Gruppen - spezielle Hinweise und Prüfungen für unprivilegierte Proxmox-LXC-Container Das Skript ist so ausgelegt, dass möglichst wenige Angaben manuell notwendig sind. Wo möglich, werden Informationen über DNS oder aus dem Systemkontext ermittelt. ## Kurzbeschreibung des Ablaufs Der grobe Ablauf ist: 1. Root-Rechte prüfen. 2. Umgebung erkennen: VM, LXC oder unbekannter Container. 3. Benötigte Pakete installieren. 4. Bei LXC: vorhandenes UID-/GID-Mapping prüfen. 5. Fehlende AD-Parameter interaktiv abfragen. 6. DNS-Konfiguration vorbereiten oder bestehende DNS-Konfiguration beibehalten. 7. Zeitsynchronisierung aktivieren. 8. Hostname setzen. 9. Bestehenden Realm erkennen und optional verlassen. 10. Kerberos-Konfiguration schreiben. 11. Active-Directory-Join durchführen. 12. SSSD konfigurieren. 13. PAM-Home-Verzeichnisse aktivieren. 14. Optional Sudo-Gruppen aus AD auswählen oder manuell eintragen. 15. Validierung über `realm`, `sssctl`, `getent` und `id` vorbereiten. ## Dialoge, Fallbacks und interaktive Eingaben Das Skript verwendet bevorzugt `dialog`, sofern es installiert ist und ein interaktives TTY verfügbar ist. Andernfalls wird für einfache Eingaben auf `read` zurückgegriffen. Interaktive Dialoge können auftreten für: - AD-Domain-FQDN - Join-Benutzer - Join-Passwort - Entscheidung bei bereits bestehender Domain-Mitgliedschaft - optionales Zurücksetzen des SSSD-ID-Mappings - Sudo-Gruppenfilter - Auswahl von AD-Gruppen für Sudo - manuelle Sudo-Gruppeneingabe, falls AD-Gruppen nicht enumeriert werden können ### Fallbacks Das Skript enthält mehrere Fallbacks: - Wenn keine DNS-Server über NS-Records gefunden werden, bleibt die vorhandene Resolver-Konfiguration erhalten. - Wenn `systemd-timesyncd` nicht verfügbar ist, wird auf `chrony` zurückgegriffen. - Wenn AD-Gruppen nicht enumeriert werden können, wird ein manueller Eingabedialog für eine einzelne Sudo-Gruppe angezeigt. - Wenn bei dieser manuellen Sudo-Gruppeneingabe nichts eingetragen wird, wird kein Sudoers-Eintrag angelegt. - Wenn SSSD-Credential-Caching aktiviert wurde, aber der Kernel-Keyring nicht nutzbar ist, bleibt Credential-Caching deaktiviert. ## Parameter und Umgebungsvariablen Viele Dialogwerte können direkt beim Aufruf über Umgebungsvariablen vorbelegt werden. ### Active Directory und Join | Variable | Standard | Beschreibung | |---|---:|---| | `AD_DOMAIN_FQDN` | leer | FQDN der AD-Domäne, z. B. `corp.example.com` | | `AD_JOIN_USER` | leer | Benutzer für den Domain-Join, ohne Domain-Präfix | | `AD_OU_DN` | leer | Optionale OU für das Computerobjekt, z. B. `OU=Linux,OU=Servers,DC=corp,DC=example,DC=com` | | `COMPUTER_NAME` | `hostname -s` | Kurzer Hostname für das System | | `USE_FQ_NAMES` | `false` | `true` verwendet vollständig qualifizierte Benutzernamen | | `DISABLE_DNS_AUTOCONFIG` | `false` | `true` verhindert automatische DNS-Konfiguration | ### Session und PAM | Variable | Standard | Beschreibung | |---|---:|---| | `SESSION_TIMEOUT_SECONDS` | `7200` | Inaktivitäts-Timeout für interaktive Shells; `0` deaktiviert den Timeout | | `PAM_UMASK` | `0027` | Umask für automatisch erstellte Home-Verzeichnisse | ### SSSD-ID-Mapping | Variable | Standard | Beschreibung | |---|---:|---| | `LXC_IDMAP_RANGE_SIZE` | `1000000` | Anzahl der im LXC-Namespace gemappten IDs pro Container | | `IDMAP_RANGE_MIN` | `100000` | Erste von SSSD für AD-Mapping verwendete ID im Container | | `IDMAP_RANGE_SIZE` | `LXC_IDMAP_RANGE_SIZE - IDMAP_RANGE_MIN` | Größe des SSSD-ID-Bereichs | | `IDMAP_RANGE_MAX` | `IDMAP_RANGE_MIN + IDMAP_RANGE_SIZE - 1` | Letzte von SSSD verwendbare ID | Mit den Standardwerten ergibt sich: ```text LXC-Namespace: 0 - 999999 SSSD/AD-IDs: 100000 - 999999 ``` ### Sudo-Gruppen | Variable | Standard | Beschreibung | |---|---:|---| | `SUDO_GROUP_FILTER` | `LINUX` | Filter für die interaktive AD-Gruppenauswahl | | `SUDOERS_DROPIN_FILE` | `/etc/sudoers.d/90-ad-groups` | Zielpfad für den generierten Sudoers-Drop-in | ### Credential-Caching | Variable | Standard | Beschreibung | |---|---:|---| | `ENABLE_CREDENTIAL_CACHING` | `false` | Aktiviert SSSD-Credential-Caching nur, wenn der Kernel-Keyring nutzbar ist | ## Beispielaufrufe Minimaler interaktiver Aufruf: ```bash sudo ./domain-join.sh ``` Aufruf mit vorbelegter Domain und Join-Benutzer: ```bash sudo AD_DOMAIN_FQDN="corp.example.com" \ AD_JOIN_USER="joinuser" \ ./domain-join.sh ``` Aufruf mit Computer-OU und deaktivierter DNS-Autokonfiguration: ```bash sudo AD_DOMAIN_FQDN="corp.example.com" \ AD_JOIN_USER="joinuser" \ AD_OU_DN="OU=Linux,OU=Servers,DC=corp,DC=example,DC=com" \ DISABLE_DNS_AUTOCONFIG=true \ ./domain-join.sh ``` Aufruf mit vollständig qualifizierten Benutzernamen: ```bash sudo AD_DOMAIN_FQDN="corp.example.com" \ AD_JOIN_USER="joinuser" \ USE_FQ_NAMES=true \ ./domain-join.sh ``` Aufruf ohne Session-Timeout: ```bash sudo SESSION_TIMEOUT_SECONDS=0 ./domain-join.sh ``` Aufruf mit Credential-Caching, sofern der Container beziehungsweise Kernel-Keyring dies erlaubt: ```bash sudo ENABLE_CREDENTIAL_CACHING=true ./domain-join.sh ``` ## Technischer Ablauf im Detail ### 1. Paketinstallation Das Skript installiert unter anderem: - `realmd` - `adcli` - `sssd` - `sssd-tools` - `libnss-sss` - `libpam-sss` - `krb5-user` - `samba-common-bin` - `dnsutils` - `ldap-utils` - `dialog` - `keyutils` Vorher werden die APT-Paketlisten aktualisiert und installierte Pakete aktualisiert. ### 2. DNS-Erkennung Die Domain Controller werden über SRV-Records gesucht: ```text _ldap._tcp. ``` DNS-Server werden über NS-Records der AD-Domain ermittelt. Wenn `systemd-resolved` aktiv ist, wird ein Drop-in unter `/etc/systemd/resolved.conf.d/` geschrieben. Andernfalls wird `/etc/resolv.conf` direkt geschrieben, sofern die DNS-Autokonfiguration nicht deaktiviert wurde. ### 3. Zeitsynchronisierung Kerberos ist empfindlich gegenüber Zeitabweichungen. Das Skript bevorzugt deshalb `systemd-timesyncd`. Wenn dieser Dienst nicht verfügbar ist, wird `chrony` verwendet oder installiert. ### 4. Kerberos Das Skript schreibt eine minimale `/etc/krb5.conf`, die DNS-basierte Realm- und KDC-Erkennung verwendet. ### 5. Domain Join Der Join erfolgt über: ```bash realm join --verbose -U ``` Wenn `AD_OU_DN` gesetzt ist, wird zusätzlich `--computer-ou=...` verwendet. ### 6. SSSD Das Skript schreibt `/etc/sssd/sssd.conf` mit: - `id_provider = ad` - `auth_provider = ad` - `access_provider = ad` - `ldap_id_mapping = true` - konfigurierbarem ID-Mapping - deaktivierter GPO-Auswertung über `ad_gpo_access_control = disabled` - optionalem Credential-Caching Anschließend wird SSSD aktiviert und neu gestartet. ### 7. PAM-Home-Verzeichnisse Das Skript stellt sicher, dass `pam_mkhomedir.so` in folgenden Dateien vorhanden ist: - `/etc/pam.d/common-session` - `/etc/pam.d/common-session-noninteractive` Dadurch werden Home-Verzeichnisse für AD-Benutzer beim ersten Login automatisch erzeugt. ## Besonderheiten bei Proxmox LXC Unprivilegierte Proxmox-LXC-Container verwenden User Namespaces. Dadurch werden Container-UIDs und Container-GIDs auf Host-UIDs und Host-GIDs gemappt. Das Skript läuft innerhalb des Containers. Deshalb kann es die Host-Konfiguration nicht selbst ändern. Es kann aber prüfen, wie der Container aktuell gemappt ist. Dazu werden ausgewertet: ```text /proc/self/uid_map /proc/self/gid_map ``` Die Host-Hinweise werden nur ausgegeben, wenn das aktuelle Mapping den benötigten Bereich nicht abdeckt. ### Erwartetes Mapping Das Skript erwartet standardmäßig einen Container-Namespace mit 1.000.000 IDs: ```text Container IDs: 0 - 999999 ``` Das zugehörige Hostschema ist: ```text 000000 - 999999 ``` Die Proxmox-Konfiguration wird dabei bewusst mit Platzhaltern dokumentiert: ```text /etc/pve/lxc/.conf lxc.idmap: u 0 000000 1000000 lxc.idmap: g 0 000000 1000000 /etc/subuid root:000000:1000000 /etc/subgid root:000000:1000000 Restart: pct restart ``` Dabei ist `` durch die tatsächliche Proxmox-Container-ID zu ersetzen. ### Beispielhafte Berechnung Für eine dreistellige CTID wird der Hostbereich durch Anhängen von sechs Nullen gebildet. Schema: ```text Host-Basis = 000000 ``` Die README verwendet bewusst keine konkrete Container-ID in der Anleitung, damit die Konfiguration nicht versehentlich kopiert wird, ohne `` zu ersetzen. ## SSSD-ID-Mapping und Container-Namespace SSSD erzeugt die AD-UIDs und AD-GIDs innerhalb des Containers. Diese IDs müssen vollständig im Container-Namespace enthalten sein. Mit den Standardwerten gilt: ```text Container-Namespace: 0 - 999999 SSSD-ID-Bereich: 100000 - 999999 ``` Dadurch bleiben IDs unterhalb von `100000` für lokale und systemnahe Konten reserviert. SSSD nutzt den restlichen Bereich. Wichtig: ```text LXC_IDMAP_RANGE_SIZE muss größer als IDMAP_RANGE_MAX sein. ``` Das Skript prüft diese Bedingung und bricht mit einer Fehlermeldung ab, wenn der Namespace zu klein ist. ## Sudo-Berechtigungen über AD-Gruppen Das Skript kann AD-Gruppen sudo-Berechtigungen geben, indem es einen Drop-in unter `/etc/sudoers.d/` erzeugt. Der Standardpfad ist: ```text /etc/sudoers.d/90-ad-groups ``` Die Gruppenauswahl erfolgt bevorzugt über eine temporäre Aktivierung von SSSD-Enumeration: ```text enumerate = true ``` Danach wird die Enumeration wieder deaktiviert: ```text enumerate = false ``` Falls das AD keine Gruppenliste zurückgibt oder Enumeration nicht erlaubt ist, wird ein manueller Eingabedialog angezeigt. Dort kann genau eine AD-Gruppe eingetragen werden. Wenn die Eingabe leer bleibt, wird kein Sudoers-Eintrag angelegt. Ein vorhandener, vom Skript verwalteter Drop-in wird dann entfernt. Gruppennamen mit Leerzeichen werden für sudoers escaped. Aus: ```text Domain Admins ``` wird: ```sudoers %Domain\ Admins ALL=(ALL:ALL) ALL ``` Die erzeugte Sudoers-Konfiguration wird mit `visudo -cf /etc/sudoers` validiert. Wenn die Validierung fehlschlägt, wird der Drop-in entfernt und das Skript bricht ab. ## Validierung nach dem Lauf Nach erfolgreichem Skriptlauf sollten folgende Prüfungen durchgeführt werden: ```bash realm list ``` ```bash sssctl config-check ``` ```bash sssctl domain-status ``` ```bash getent passwd ``` ```bash id ``` SSH-Test: ```bash ssh @ ``` Wenn vollständig qualifizierte Namen aktiviert wurden, muss der Benutzername entsprechend mit Domain angegeben werden, abhängig von der SSSD-Konfiguration. ## Bemerkungen und TODOs ### Bemerkungen - Das Skript ist für Ubuntu-Systeme vorgesehen. - Die LXC-Hostkonfiguration muss auf dem Proxmox-Host erfolgen. - Das Skript kann die Proxmox-Hostdateien aus dem Container heraus nicht selbst ändern. - Die UID-/GID-Map-Prüfung verhindert unnötige Hinweise, wenn das Mapping bereits korrekt eingerichtet wurde. - Bei Änderungen an `IDMAP_RANGE_*` sollte der SSSD-Cache zurückgesetzt werden, damit alte Mappingdaten nicht weiterverwendet werden. - Für unprivilegierte Container kann `keyctl` eingeschränkt sein. Credential-Caching bleibt deshalb standardmäßig deaktiviert. ### TODOs - Optional mehrere manuell eingegebene Sudo-Gruppen unterstützen. - Optional nicht-interaktiven Modus mit vollständiger Vorkonfiguration ergänzen. - Optional `--help` oder `usage()` für alle Parameter ergänzen. - Optional `--dry-run` für reine Prüfung ohne Änderungen ergänzen. - Optional Logging in eine Datei ergänzen. - Optional systemd-resolved-Konfiguration genauer an bestehende lokale Resolver-Policies anpassen. - Optional Re-Join-Verhalten über explizite Parameter steuerbar machen. - Optional Tests für ShellCheck, Bats oder Container-Testläufe ergänzen.