ADR-0024: one FreeIPA replaces OpenLDAP — write the ADR, implement the IPA side in ansible #316

Closed
opened 2026-08-10 14:07:35 +02:00 by dominik.polakovics · 0 comments

Scope

Two deliverables, one issue: (1) ADR-0024 recording the full decision set below, (2) the complete IPA-side implementation in ansible/ so that a playbook run leaves ipa.cloonar.com fully structured. No NixOS consumer changes here — those are the follow-up issue.

Decisions the ADR must record

  1. One FreeIPA (ipa.cloonar.com, realm CLOONAR.COM) replaces OpenLDAP entirely (slapd, all nine databases, custom schemas, phpldapadmin). Supersedes the FreeIPA rejections in ADR-0022/0023 and replaces the unimplemented parts of ADR-0023 (mail-KDC-authoritative, {CRYPT}! partition).
  2. Domains are data, not tenants: every hosted user (cloonar, macher.solutions, superbros.tv, …) lives in the one IPA; mail domain = mail attribute + a group; fleet-wide unique uid; login by email everywhere.
  3. All Kerberos principals in CLOONAR.COM; mail's standalone KDC retires; service keytabs re-issued from IPA together with each consumer's kdc= flip.
  4. Mail routing (domains, aliases) moves to Nix-generated Postfix maps; Dovecot single passdb/userdb with auth_bind = yes against IPA, login by mail=%u.
  5. Keycloak: one realm, one LDAP federation to IPA, SPNEGO keytab from IPA; Authelia retires at the end.
  6. Quotas as IPA attributes (mailQuota, cloudQuota, opt. mailSendOnly) in a custom auxiliary class, editable via an IPA Web UI plugin; Dovecot reads mailQuota; Nextcloud keeps user_ldap (internal username = uid, quota field = cloudQuota) with oidc_login proxy mode; IPA is the only quota writer.
  7. Five group layers, users only ever placed in layer 1, IPA flattens nesting: (1) people admins/staff/<domain>-users; (2) service access svc-*, every one enforced; (3) in-app roles only where consumed; (4) collaboration cloud-*/git-*, app-prefixed, never gates; (5) Unix — the only POSIX groups (unix-admins, adm-*).
  8. No username ever in NixOS config — Nix references IPA group names only (HBAC default-deny for SSH, sss_ssh_authorizedkeys for keys, sudo via %adm-* group rules, pam_group for workstation hardware groups). New user = IPA operations only, zero commits.
  9. Per-customer IPA playbook stays on the shelf for genuinely external orgs; not part of the mail story.

Ansible implementation (idempotent, re-run = update path, per existing role conventions)

  • Schema extension: auxiliary objectclass (e.g. cloonarAccount: mailQuota, cloudQuota, mailSendOnly) via LDIF/ipa-ldap-updater; add it to ipaconfig default user objectclasses so new users carry it.
  • Web UI / API plugin exposing the quota fields on the user page (documented "Extending FreeIPA: user plugins" path); deployed as files + httpd restart by the role.
  • Group structure: all five layers created idempotently, including the nesting memberships (admins → all svc-*; staff → standard set; <domain>-users → their granted set; layer-1 → collaboration groups). Layer 5 groups POSIX, everything else non-POSIX.
  • Hostgroups servers / workstations.
  • HBAC: disable allow_all; hbac-admins-all (unix-admins → both hostgroups, services sshd, login, sudo).
  • System/bind accounts (cn=sysaccounts,cn=etc) for the NixOS consumers: dovecot, keycloak, nextcloud user_ldap, home-assistant — read-only, per-service, passwords in the per-server sops file per the existing security invariant.
  • Verify role: extend acceptance checks — schema present, groups resolve with flattened memberOf, HBAC allow_all disabled, a test lookup of the quota attribute.

ADR structure/tone per existing docs/adr/; considered-options sections can draw on the discussion summarized above.

## Scope Two deliverables, one issue: (1) ADR-0024 recording the full decision set below, (2) the complete IPA-side implementation in `ansible/` so that a playbook run leaves `ipa.cloonar.com` fully structured. No NixOS consumer changes here — those are the follow-up issue. ## Decisions the ADR must record 1. One FreeIPA (`ipa.cloonar.com`, realm `CLOONAR.COM`) replaces OpenLDAP entirely (slapd, all nine databases, custom schemas, phpldapadmin). Supersedes the FreeIPA rejections in ADR-0022/0023 and replaces the unimplemented parts of ADR-0023 (mail-KDC-authoritative, `{CRYPT}!` partition). 2. Domains are data, not tenants: every hosted user (cloonar, macher.solutions, superbros.tv, …) lives in the one IPA; mail domain = `mail` attribute + a group; fleet-wide unique uid; login by email everywhere. 3. All Kerberos principals in `CLOONAR.COM`; mail's standalone KDC retires; service keytabs re-issued from IPA together with each consumer's `kdc=` flip. 4. Mail routing (domains, aliases) moves to Nix-generated Postfix maps; Dovecot single passdb/userdb with `auth_bind = yes` against IPA, login by `mail=%u`. 5. Keycloak: one realm, one LDAP federation to IPA, SPNEGO keytab from IPA; Authelia retires at the end. 6. Quotas as IPA attributes (`mailQuota`, `cloudQuota`, opt. `mailSendOnly`) in a custom auxiliary class, editable via an IPA Web UI plugin; Dovecot reads `mailQuota`; Nextcloud keeps `user_ldap` (internal username = `uid`, quota field = `cloudQuota`) with `oidc_login` proxy mode; IPA is the only quota writer. 7. Five group layers, users only ever placed in layer 1, IPA flattens nesting: (1) people `admins`/`staff`/`<domain>-users`; (2) service access `svc-*`, every one enforced; (3) in-app roles only where consumed; (4) collaboration `cloud-*`/`git-*`, app-prefixed, never gates; (5) Unix — the only POSIX groups (`unix-admins`, `adm-*`). 8. No username ever in NixOS config — Nix references IPA group names only (HBAC default-deny for SSH, `sss_ssh_authorizedkeys` for keys, sudo via `%adm-*` group rules, `pam_group` for workstation hardware groups). New user = IPA operations only, zero commits. 9. Per-customer IPA playbook stays on the shelf for genuinely external orgs; not part of the mail story. ## Ansible implementation (idempotent, re-run = update path, per existing role conventions) - **Schema extension**: auxiliary objectclass (e.g. `cloonarAccount`: `mailQuota`, `cloudQuota`, `mailSendOnly`) via LDIF/`ipa-ldap-updater`; add it to `ipaconfig` default user objectclasses so new users carry it. - **Web UI / API plugin** exposing the quota fields on the user page (documented "Extending FreeIPA: user plugins" path); deployed as files + httpd restart by the role. - **Group structure**: all five layers created idempotently, including the nesting memberships (`admins` → all `svc-*`; `staff` → standard set; `<domain>-users` → their granted set; layer-1 → collaboration groups). Layer 5 groups POSIX, everything else non-POSIX. - **Hostgroups** `servers` / `workstations`. - **HBAC**: disable `allow_all`; `hbac-admins-all` (`unix-admins` → both hostgroups, services `sshd`, `login`, `sudo`). - **System/bind accounts** (`cn=sysaccounts,cn=etc`) for the NixOS consumers: dovecot, keycloak, nextcloud `user_ldap`, home-assistant — read-only, per-service, passwords in the per-server sops file per the existing security invariant. - **Verify role**: extend acceptance checks — schema present, groups resolve with flattened memberOf, HBAC `allow_all` disabled, a test lookup of the quota attribute. ADR structure/tone per existing `docs/adr/`; considered-options sections can draw on the discussion summarized above.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/nixos#316
No description provided.