Files
git.stella-ops.org/docs/rfcs/authority-plugin-ldap.md
master b97fc7685a
Some checks failed
Build Test Deploy / authority-container (push) Has been cancelled
Build Test Deploy / docs (push) Has been cancelled
Build Test Deploy / deploy (push) Has been cancelled
Build Test Deploy / build-test (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Initial commit (history squashed)
2025-10-11 23:28:35 +03:00

8.7 KiB
Raw Blame History

RFC: StellaOps.Authority.Plugin.Ldap

Status: Draft for review by Auth Guild, Security Guild, DevEx (2025-10-10)
Authors: Plugin Team 4 (Auth Libraries & Identity Providers)
Related initiatives: PLG7 backlog, CORE5 event handlers, DOC4 developer guide

1. Problem Statement

Many on-prem StellaOps deployments rely on existing LDAP/Active Directory domains for workforce identity. The current Standard Mongo-backed plugin requires duplicating users and secrets, which increases operational overhead and violates corporate policy in some regulated environments. We need a sovereign, offline-friendly LDAP plugin that:

  • Supports password grant and bootstrap provisioning flows without storing credentials in Mongo.
  • Enforces StellaOps security policies (lockout, password policy hints, audit logging) while delegating credential validation to LDAP.
  • Operates deterministically in offline or partially connected environments by caching directory metadata when necessary.

2. Goals

  • Provide a first-party StellaOps.Authority.Plugin.Ldap plugin advertising password and optional clientProvisioning capabilities at launch.
  • Support username/password authentication against LDAP bind operations with configurable DN templates.
  • Allow optional bootstrap seeding of service accounts by writing into LDAP (guarded behind explicit configuration) or by mapping to pre-existing entries.
  • Surface directory-derived claims (groups, attributes) for downstream authorization via IClaimsEnricher.
  • Integrate with Authority lockout telemetry and structured logging without persisting secrets locally.

3. Non-Goals

  • Implement multi-factor authentication out of the box (future enhancement once TOTP/WebAuthn strategy is finalised).
  • Provide write-heavy directory management (e.g., user creation workflows) beyond optional bootstrap service account seeding.
  • Replace the Standard plugin; both must remain supported and selectable per environment.

4. Key Constraints & Assumptions

  • Offline-first posture: deployments may operate without outbound internet and with intermittent directory connectivity (e.g., read-only replicas). The plugin must tolerate transient LDAP connectivity failures and degrade gracefully.
  • Deterministic behaviour: identical configuration and directory state must yield identical token issuance results. Cached metadata (e.g., group lookups) must have defined expiration.
  • Security: No plaintext credential storage; TLS must be enforced for LDAP connections unless explicitly overridden for air-gapped lab environments.

5. High-Level Architecture

  1. Configuration binding (ldap.yaml): defines server endpoints, bind strategy, claim mapping, and optional bootstrap overrides.
  2. Connection factory: pooled LDAP connections using a resilient client (preferred dependency: Novell.Directory.Ldap.NETStandard).
  3. Credential validator (IUserCredentialStore): performs bind-as-user flow with optional fallback bind using service account when directories disallow anonymous search.
  4. Claims enricher (IClaimsEnricher): queries group membership/attributes and projects them into canonical roles/claims.
  5. Optional client provisioning (IClientProvisioningStore): maintains machine/service principals either in Mongo (metadata) or via LDAP serviceConnectionPoint entries based on configuration.
  6. Health checks: periodic LDAP whoami or search probes surfaced through AuthorityPluginHealthResult.
Authority Host
 ├── Plugin Manifest (ldap)
 ├── Registrar → registers ConnectionFactory, LdapCredentialStore, LdapClaimsEnricher
 ├── Password Grant Handler → CredentialStore.VerifyPasswordAsync → LDAP Bind
 └── Claims Pipeline → ClaimsEnricher.EnrichAsync → LDAP group lookup

6. Configuration Schema (Draft)

connection:
  host: "ldaps://ldap.example.internal"
  port: 636
  useStartTls: false
  validateCertificates: true
  bindDn: "cn=stellaops-bind,ou=service,dc=example,dc=internal"
  bindPasswordSecret: "file:/etc/stellaops/secrets/ldap-bind.txt"
  searchBase: "dc=example,dc=internal"
  usernameAttribute: "uid"
  userDnFormat: "uid={username},ou=people,dc=example,dc=internal"  # optional template
security:
  requireTls: true
  allowedCipherSuites: []          # optional allow-list
  referralChasing: false
lockout:
  useAuthorityPolicies: true       # reuse Authority lockout counters
  directoryLockoutAttribute: "pwdAccountLockedTime"
claims:
  groupAttribute: "memberOf"
  groupToRoleMap:
    "cn=stellaops-admins,ou=groups,dc=example,dc=internal": "operators"
    "cn=stellaops-read,ou=groups,dc=example,dc=internal": "auditors"
  extraAttributes:
    displayName: "displayName"
    email: "mail"
clientProvisioning:
  enabled: false
  containerDn: "ou=service,dc=example,dc=internal"
  secretAttribute: "userPassword"
health:
  probeIntervalSeconds: 60
  timeoutSeconds: 5

7. Capability Mapping

Capability Implementation Notes
password Bind-as-user validation with Authority lockout integration. Mandatory.
clientProvisioning Optional; when enabled, creates/updates LDAP entries for machine clients or stores metadata in Mongo if directory writes are disabled.
bootstrap Exposed only when bootstrap manifest provides service account credentials AND directory write permissions are confirmed during startup.
mfa Not supported in MVP. Future iteration may integrate TOTP attributes or external MFA providers.

8. Operational Considerations

  • Offline cache: provide optional Mongo cache for group membership to keep /ready responsive if LDAP is temporarily unreachable. Cache entries must include TTL and invalidation hooks.
  • Secrets management: accept file: and environment variable references; integrate with existing StellaOps.Configuration secret providers.
  • Observability: emit structured logs with event IDs (LDAP_BIND_START, LDAP_BIND_FAILURE, LDAP_GROUP_LOOKUP), counters for success/failure, and latency histograms.
  • Throttling: reuse Authority rate-limiting middleware; add per-connection throttles to avoid saturating directory servers during brute-force attacks.

9. Security & Compliance

  • Enforce TLS (ldaps:// or STARTTLS) by default. Provide explicit allowInsecure flag gated behind environment variable for lab/testing only.
  • Support password hash migration by detecting directory lockout attributes and surfacing RequiresPasswordReset when policies demand changes.
  • Log distinguished names only at Debug level to avoid leaking sensitive structure in default logs.
  • Coordinate with Security Guild for penetration testing before GA; incorporate audit log entries for bind attempts and provisioning changes.

10. Testing Strategy

  • Unit tests: mock LDAP connections to validate DN formatting, error mapping, and capability negotiation.
  • Integration tests: run against an ephemeral OpenLDAP container (seeded via LDIF fixtures) within CI. Include offline cache regression (disconnect LDAP mid-test).
  • Determinism tests: feed identical LDIF snapshots and configuration to ensure output tokens/claims remain stable across runs.
  • Smoke tests: dotnet test harness plus manual dotnet run scenario verifying /token password grants and /internal/users bootstrap with LDAP-backed store.

11. Implementation Plan

  1. Scaffold StellaOps.Authority.Plugin.Ldap project + tests (net10.0, <IsAuthorityPlugin> true).
  2. Implement configuration options + validation (mirroring Standard plugin guardrails).
  3. Build connection factory + credential store with bind logic.
  4. Implement claims enricher and optional cache layer.
  5. Add client provisioning store (optional) with toggles for read-only deployments.
  6. Wire bootstrapper to validate connectivity/permissions and record findings in startup logs.
  7. Extend developer guide with LDAP specifics (post-RFC acceptance).
  8. Update Docs and TODO trackers; produce release notes entry once merged.

12. Open Questions

  • Should client provisioning default to storing metadata in Mongo even when LDAP writes succeed (to preserve audit history)?
  • Do we require LDAPS mutual TLS support (client certificates) for regulated environments? If yes, need to extend configuration schema.
  • How will we map LDAP groups to Authority scopes/roles when names differ significantly? Consider supporting regex or mapping scripts.

13. Timeline (Tentative)

  • Week 1: RFC review & sign-off.
  • Week 2-3: Implementation & unit tests.
  • Week 4: Integration tests + documentation updates.
  • Week 5: Security review, release candidate packaging.

14. Approval

  • Auth Guild Lead: TBD
  • Security Guild Representative: TBD
  • DevEx Docs: TBD

Please add comments inline or via PR review. Once approved, track execution under PLG7.