Skip to content

feat(core): PAM system-user authentication backend#1317

Open
geoffjay wants to merge 10 commits into
feature/pam-authfrom
pam
Open

feat(core): PAM system-user authentication backend#1317
geoffjay wants to merge 10 commits into
feature/pam-authfrom
pam

Conversation

@geoffjay

Copy link
Copy Markdown
Owner

Summary

Adds PAM (system-user) authentication to agentd-core as a pluggable login backend alongside the existing argon2 database-password auth. This lets people log in with their OS credentials — the same system identity agents already run under via sudo -u <user>.

PAM is opt-in and pluggable, not a replacement:

  • Each user has an auth_provider: local (argon2, the default + bootstrap/superuser/test escape hatch) or pam.
  • First-time PAM login by username just-in-time provisions the app user + a personal org (mirroring registration), linked to the OS account via system_username.
  • Local password auth is completely unaffected, even with PAM enabled.

The only behavioral change to the login path is the credential-check branch in login_handler; sessions, tokens, and middleware are untouched.

Cross-platform (macOS + Linux)

The verifier works on both macOS (OpenPAM) and Linux (Linux-PAM) from the same code, built on raw pam-sys bindings plus a small hand-written conversation (no bindgen/libclang). The one real ABI difference — OpenPAM passes a contiguous message array, Linux-PAM an array of pointers — is isolated in a single cfg-gated helper. Verified at runtime on macOS against the built-in chkpasswd service (real pam_start → conversation → pam_authenticatepam_end round-trip).

Build & install

  • pam Cargo feature, off by default, gated to cfg(unix). Builds without it need no PAM library.
  • AGENTD_PAM=1 cargo xtask install-user produces a PAM-enabled agentd-core; plain install-user is unchanged.
  • New CI job builds + clippies --features pam on macOS and Linux.

Privilege model

  • macOS dev: no setup — pam_opendirectory verifies without root.
  • Linux prod: because unix_chkpwd only verifies the caller's own account, core must run as a system service with its account in the shadow group (or use an SSSD-backed stack). This touches systemd unit privileges (human-approval-adjacent per docs/planning/autonomous-pipeline-gates.md), so the installer does not apply it automatically — see docs/pam-authentication.md.

Config

AGENTD_PAM_ENABLED (master switch), AGENTD_PAM_SERVICE (default agentd), AGENTD_PAM_EMAIL_DOMAIN (default pam.local).

Testing

  • 125 unit/integration tests pass, including 7 new PAM tests (via a mock verifier): JIT provisioning, idempotency, 401 on reject, 500 on unavailable stack, disabled, by-email no-provision, local-user-unaffected.
  • tests/pam_smoke.rs (--ignored, --features pam) drives the real stack; wrong-password case ran green on macOS.
  • cargo fmt --check and clippy (default + --features pam --all-targets) pass.

Note

Per the branch strategy this targets feature/pam-auth, not main.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant