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

4.8 KiB

LDAP 📒

This page describes how application roles consume the platform's LDAP provider, OpenLDAP. The variable tree lives in 12_ldap.yml under LDAP. For the cross-cutting IAM principles, including the paired identifier rule shared with OIDC, see common.md. For OIDC-side details see 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 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 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.

File Purpose
12_ldap.yml LDAP SPOT, defines LDAP.*
svc-db-openldap LDAP provider role
oidc.md OIDC-side counterpart, paired user identifier
common.md Cross-cutting IAM principles and integration checklist