Linux auth: remaining work before an initial release #1

Open
opened 2026-06-24 16:20:19 +00:00 by franz · 1 comment
Owner

Tracking issue for the remaining work on the Linux-authentication feature. The bulk of the engineering is done and verified; what's left is mostly packaging, integration hygiene, and a couple of deliberate scoping decisions before an initial (Guix) release.

All of the work below lives on the feature/linux branch (~55 commits ahead of master).

Done (for context)

  • M1 - resolution spine + key login: POSIX data model, resolver API, host enrollment/rotation, admin UI, seat-cap gate, identity-delete cascade, forseti-unix client (daemon + thin NSS + authorized-keys), pam_mkhomedir, Guix package/service.
  • M2 - interactive login via the OAuth 2.0 Device Authorization Grant (RFC 8628), Forseti-mediated. Verified live against real Hydra/Kratos; hardened across a 3-round adversarial review (panic-guarded PAM .so, bounded daemon socket, unique user_code, exact-aud id_token pin).
  • M4 account fail-closed - a daemon outage denies Forseti (NSS-only) users but local/root logins survive (via a getspnam classifier). Proven in the marionette VM.
  • M3a - offline terminal login via a dedicated ≥8-char passphrase (never the primary credential), verified HMAC(host_pepper, Argon2id(passphrase)), force_mfa hosts refuse offline. Verified: 344 unit + 3/3 live offline integration tests + 14/14 marionette VM assertions (genuine offline login with the server unreachable).
  • Docs kept in sync (docs/dev/flows.md, docs/operator-guide.md, CHANGELOG.md).

Release blockers

  • panther: commit the Guix package bits. px/packages/authentication.scm (installs pam_forseti.so) and px/packages/rust-crates.scm (missing the M3a crypto crates: argon2, hmac, sha2, subtle, async-trait + transitives) are uncommitted. The Guix package — the intended initial-release vehicle — does not build without them.
  • Merge feature/linuxmaster (~55 commits), ideally with a final review pass on the merged diff. A release ships from master/a tag.

Gaps to close before shipping an auth feature

  • Add the forseti-unix workspace to CI. CI currently runs make check (main crate) + the posix server integration job, but the host-side workspace (daemon/pam/nss) is never built or tested in CI, so host-side regressions would ship silently. Add a job: cargo check + cargo clippy -D warnings + cargo test for forseti-unix (the marionette KVM test can stay out of CI for now).
  • Clean-room operator walkthrough. On a fresh system, enroll a host -> install the package -> actually ssh in, following only the docs. The VM proves components; this proves the docs/UX. Plus one manual smoke test of real ssh user@host device-auth over keyboard-interactive (the in-VM assertion hits a known harness limitation, so this path is currently proven only by component).

v1 scoping decisions

  • Default M3a offline auth to opt-in (off) for v1. It currently defaults offline_auth_enabled = true; flipping to false is a one-line change. It's new, and the no-TPM guarantee is reduced — better to let operators opt in knowingly until M3b lands.
  • Label the Linux-auth feature "preview/experimental" in the release notes, with M3b/M3c roadmapped.

Roadmap (post-v1)

  • M3b - TPM sealing. Move the host pepper into a TPM-resident HMAC so a stolen disk can't brute-force the verifier. Plan drafted (TODO_LINUX_M3b.md): use kanidm-hsm-crypto, sealed loadable key blob (no PCR sealing), off/auto/required tri-state, prove the TPM path with a host-level swtpm integration test (Guix has no vTPM-marionette precedent). The 3-expert plan-challenge round is still pending.
  • M3c - TPM-bound offline grant. A pre-fetched, host-TPM-bound short-lived assertion redeemed offline with no memorized secret — better UX for single-user laptops. Own plan.
  • Residuals: initgroups_dyn in NSS, private_key_jwt for the PAM client, roadmap M4 (systemd packaging).

Notes

  • The non-blocking marionette failure ("interactive device-auth ssh succeeds") is a structural sshd keyboard-interactive / PAM re-invocation limitation, not a product bug — documented, not masked.
Tracking issue for the remaining work on the Linux-authentication feature. The bulk of the engineering is done and verified; what's left is mostly packaging, integration hygiene, and a couple of deliberate scoping decisions before an initial (Guix) release. All of the work below lives on the `feature/linux` branch (~55 commits ahead of `master`). ## Done (for context) - **M1** - resolution spine + key login: POSIX data model, resolver API, host enrollment/rotation, admin UI, seat-cap gate, identity-delete cascade, `forseti-unix` client (daemon + thin NSS + authorized-keys), `pam_mkhomedir`, Guix package/service. - **M2** - interactive login via the OAuth 2.0 Device Authorization Grant (RFC 8628), Forseti-mediated. Verified live against real Hydra/Kratos; hardened across a 3-round adversarial review (panic-guarded PAM `.so`, bounded daemon socket, unique `user_code`, exact-`aud` id_token pin). - **M4 account fail-closed** - a daemon outage denies Forseti (NSS-only) users but local/root logins survive (via a `getspnam` classifier). Proven in the marionette VM. - **M3a** - offline terminal login via a dedicated ≥8-char passphrase (never the primary credential), verified `HMAC(host_pepper, Argon2id(passphrase))`, force_mfa hosts refuse offline. Verified: 344 unit + 3/3 live offline integration tests + 14/14 marionette VM assertions (genuine offline login with the server unreachable). - Docs kept in sync (`docs/dev/flows.md`, `docs/operator-guide.md`, `CHANGELOG.md`). ## Release blockers - [ ] **panther: commit the Guix package bits.** `px/packages/authentication.scm` (installs `pam_forseti.so`) and `px/packages/rust-crates.scm` (missing the M3a crypto crates: `argon2`, `hmac`, `sha2`, `subtle`, `async-trait` + transitives) are uncommitted. The Guix package — the intended initial-release vehicle — does not build without them. - [ ] **Merge `feature/linux` → `master`** (~55 commits), ideally with a final review pass on the merged diff. A release ships from `master`/a tag. ## Gaps to close before shipping an auth feature - [ ] **Add the `forseti-unix` workspace to CI.** CI currently runs `make check` (main crate) + the posix *server* integration job, but the host-side workspace (daemon/pam/nss) is never built or tested in CI, so host-side regressions would ship silently. Add a job: `cargo check` + `cargo clippy -D warnings` + `cargo test` for `forseti-unix` (the marionette KVM test can stay out of CI for now). - [ ] **Clean-room operator walkthrough.** On a fresh system, enroll a host -> install the package -> actually `ssh in`, following only the docs. The VM proves components; this proves the docs/UX. Plus one manual smoke test of real `ssh user@host` device-auth over keyboard-interactive (the in-VM assertion hits a known harness limitation, so this path is currently proven only by component). ## v1 scoping decisions - [ ] **Default M3a offline auth to opt-in (off) for v1.** It currently defaults `offline_auth_enabled = true`; flipping to false is a one-line change. It's new, and the no-TPM guarantee is reduced — better to let operators opt in knowingly until M3b lands. - [ ] **Label the Linux-auth feature "preview/experimental"** in the release notes, with M3b/M3c roadmapped. ## Roadmap (post-v1) - [ ] **M3b - TPM sealing.** Move the host pepper into a TPM-resident HMAC so a stolen disk can't brute-force the verifier. Plan drafted (`TODO_LINUX_M3b.md`): use `kanidm-hsm-crypto`, sealed loadable key blob (no PCR sealing), `off`/`auto`/`required` tri-state, prove the TPM path with a host-level `swtpm` integration test (Guix has no vTPM-marionette precedent). The 3-expert plan-challenge round is still pending. - [ ] **M3c - TPM-bound offline grant.** A pre-fetched, host-TPM-bound short-lived assertion redeemed offline with no memorized secret — better UX for single-user laptops. Own plan. - [ ] Residuals: `initgroups_dyn` in NSS, `private_key_jwt` for the PAM client, roadmap M4 (systemd packaging). ## Notes - The non-blocking marionette failure ("interactive device-auth ssh succeeds") is a structural sshd keyboard-interactive / PAM re-invocation limitation, not a product bug — documented, not masked.
Author
Owner

Progress - v0.1.8 released (2026-06-24)

Both release blockers are closed and the feature shipped as a preview.

  • Merged + released: feature/linux squash-merged to master (c72602c) and released as v0.1.8 - https://github.com/franzos/forseti/releases/tag/v0.1.8 (46912ef, tag v0.1.8).
  • panther package committed: forseti-unix builds from the GitHub v0.1.8 source - panther commit d224400 (signed). rust-crates.scm needed no changes; the M3a crypto crates were already vendored. Push the panther channel if not already pushed.
  • Labeled "preview" in the README + CHANGELOG.
### Progress - v0.1.8 released (2026-06-24) Both release blockers are closed and the feature shipped as a preview. - Merged + released: `feature/linux` squash-merged to `master` (`c72602c`) and released as v0.1.8 - https://github.com/franzos/forseti/releases/tag/v0.1.8 (`46912ef`, tag `v0.1.8`). - panther package committed: `forseti-unix` builds from the GitHub `v0.1.8` source - panther commit `d224400` (signed). `rust-crates.scm` needed no changes; the M3a crypto crates were already vendored. Push the panther channel if not already pushed. - Labeled "preview" in the README + CHANGELOG.
Sign in to join this conversation.
No labels
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
franz/forseti#1
No description provided.