Files
computer-playbook/docs/contributing/design/iam/ldap.md
kevinveenbirkenbachandClaude Opus 4.7 9a578952c3 feat(env): SPOT env-pipeline + INFINITO_* namespace
Replace 8 bash env modules with a single Python generator
(cli.meta.env) that materialises env/static.env + runtime context
into a gitignored .env. Each variable lives in its own handler
under utils/env/handlers/; defaults carry inline one-line `# ...`
comments.

Rename to the INFINITO_* schema:
- workflow inputs: APPS, SERVICES_DISABLED, CMD, DEBUG, WHITELIST,
  BUNDLES, FULL_CYCLE, VARIANT, RUN_FLAGS, LIMIT_HOST, PARALLEL
- inventory: INVENTORY_DIR / INVENTORY_FILE / HOST_VARS_FILE,
  PW_FILE -> INVENTORY_PASSWORD_FILE
- venv: VENV_BASE / VENV_FALLBACK / VENV_NAME
- new SPOT defaults: COMPILE_SILENCE, CONTAINER_NO_CA,
  WAIT_HEALTH_TIMEOUT_S, PACKAGE_CACHE_FRONTEND_INIT_IMAGE,
  promoted IMAGE_TAG from GHA-only to general passthrough

compose.yml hardening:
- inline \${VAR:-default} removed; strict \${VAR:?...} everywhere
- new integration lint blocks regressions

Tooling:
- scripts/install/all.sh owns the stamp-file install logic
  (Makefile target delegates)
- scripts/meta/env/load.sh is the single shell entry point;
  8 bash modules deleted
- new shell lint: no INFINITO_* defaults outside env/static.env

Tests:
- 93 new unit tests for utils/env/{builder,parser,runtime,writer}
- restructure tests/lint into repository/ (file-content rules) vs
  filesystem/{shell,python,env}/ (filesystem-shape rules)
- drift + smoke integration tests against the generator

Docs:
- variables.md is now a pointer; per-variable docs live next to
  the key in env/static.env / env/ci.env
- compose.yml.md drops the Default column

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 20:40:34 +02:00

106 lines
4.8 KiB
Markdown

# LDAP 📒
This page describes how application roles consume the platform's LDAP provider, [OpenLDAP](../../../../roles/svc-db-openldap/).
The variable tree lives in [12_ldap.yml](../../../../group_vars/all/12_ldap.yml) under `LDAP`.
For the cross-cutting IAM principles, including the paired identifier rule shared with OIDC, see [common.md](common.md).
For OIDC-side details see [oidc.md](oidc.md).
## Variable Tree 🌳
The high-level structure:
| Key | Meaning |
|---|---|
| `LDAP.DN.ROOT` | Base DN derived from `DOMAIN_PRIMARY` |
| `LDAP.DN.ADMINISTRATOR.DATA` | Bind DN for CRUD on entries below `ROOT` |
| `LDAP.DN.ADMINISTRATOR.CONFIGURATION` | Bind DN for `cn=config` schema work |
| `LDAP.DN.OU.USERS` | Container for user objects |
| `LDAP.DN.OU.GROUPS` | Container for organizational groups |
| `LDAP.DN.OU.ROLES` | Container for application RBAC roles |
| `LDAP.BIND_CREDENTIAL` | Password for the data administrator DN |
| `LDAP.SERVER.DOMAIN` | Hostname or container name to dial |
| `LDAP.SERVER.PORT` | Port resolved through the ports registry |
| `LDAP.SERVER.URI` | Full `ldap[s]://host:port` URI |
| `LDAP.SERVER.SECURITY` | Transport security mode, empty when unused |
| `LDAP.NETWORK.LOCAL` | True when the consumer shares the OpenLDAP Docker network |
Rules:
- Roles MUST connect via `LDAP.SERVER.URI`. Building the URI from the
individual `INFINITO_DOMAIN`, `PORT`, and protocol parts is forbidden because the
helper variables in [12_ldap.yml](../../../../group_vars/all/12_ldap.yml)
already pick the correct scheme based on Docker-network availability.
- The data administrator DN MUST be used for adding, modifying, and removing
users, groups, and roles. The configuration administrator DN MUST be used
only for schema and overlay changes pushed via `ldapi:///`.
- New OUs SHOULD NOT be invented. Place users under `OU.USERS`, RBAC roles
under `OU.ROLES`, and organizational groups under `OU.GROUPS`.
## Object Classes 🧱
`LDAP.USER.OBJECTS` lists the structural and auxiliary object classes attached to user entries:
| Group | Key | Default | Purpose |
|---|---|---|---|
| Structural | (list) | `person`, `inetOrgPerson`, `posixAccount` | Core identity, internet attributes, UNIX account fields |
| Auxiliary | `NEXTCLOUD_USER` | `nextcloudUser` | Adds `nextcloudQuota` and `nextcloudEnabled` |
| Auxiliary | `SSH_PUBLIC_KEY` | `ldapPublicKey` | Stores SSH public keys for services like Gitea |
Each entry has exactly one structural class chain.
New auxiliary classes SHOULD be added under `LDAP.USER.OBJECTS.AUXILIARY` so consumers can probe them by symbolic name instead of literal string.
## User Attributes 🪧
`LDAP.USER.ATTRIBUTES` lists the LDAP attribute names that applications query:
| Key | Default value | Meaning |
|---|---|---|
| `LDAP.USER.ATTRIBUTES.ID` | `uid` | Login identifier, paired with the OIDC `preferred_username` |
| `LDAP.USER.ATTRIBUTES.MAIL` | `mail` | Primary email |
| `LDAP.USER.ATTRIBUTES.FULLNAME` | `cn` | Display name |
| `LDAP.USER.ATTRIBUTES.FIRSTNAME` | `givenName` | First name |
| `LDAP.USER.ATTRIBUTES.SURNAME` | `sn` | Last name |
| `LDAP.USER.ATTRIBUTES.SSH_PUBLIC_KEY` | `sshPublicKey` | SSH key attribute |
| `LDAP.USER.ATTRIBUTES.NEXTCLOUD_QUOTA` | `nextcloudQuota` | Per-user Nextcloud quota |
Rules:
- Templates MUST reference `LDAP.USER.ATTRIBUTES.*`. Hardcoded `uid`, `cn`,
or `sn` values are forbidden because the underlying schema may switch
flavor in the future.
- The login attribute is paired with the OIDC username claim by design.
Changing one without the other breaks LDAP-OIDC correlation. See
[oidc.md](oidc.md) for the OIDC-side rule.
## Filters 🔎
`LDAP.FILTERS.USERS` provides reusable LDAP search filters:
| Key | Purpose |
|---|---|
| `LDAP.FILTERS.USERS.LOGIN` | Resolve a single user by login attribute, parameterized via `%uid` |
| `LDAP.FILTERS.USERS.ALL` | Match every user entry, used for sync jobs and listings |
Roles SHOULD prefer these filters over composing new ones inline so a future schema change updates every consumer at once.
## RBAC 👥
`LDAP.RBAC` controls how application roles are represented:
| Key | Meaning |
|---|---|
| `LDAP.RBAC.FLAVORS` | Allowed group flavors, currently `groupOfNames` |
| `LDAP.RBAC.EMPTY_MEMBER_DN` | Placeholder DN for empty `groupOfNames` groups |
`groupOfNames` requires at least one `member` attribute.
The placeholder DN exists so newly created empty groups remain schema-valid until the first real member is added.
## Related Files 📚
| File | Purpose |
|---|---|
| [12_ldap.yml](../../../../group_vars/all/12_ldap.yml) | LDAP SPOT, defines `LDAP.*` |
| [svc-db-openldap](../../../../roles/svc-db-openldap/) | LDAP provider role |
| [oidc.md](oidc.md) | OIDC-side counterpart, paired user identifier |
| [common.md](common.md) | Cross-cutting IAM principles and integration checklist |