Skip to content

feat(compliance): schedule JIT expiry revocation via systemd user timer (Req-3) - #112

Open
JJediny wants to merge 1 commit into
mainfrom
feat/jit-audit-timer
Open

JJediny wants to merge 1 commit into
mainfrom
feat/jit-audit-timer

Conversation

@JJediny

@JJediny JJediny commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Why

The #82 artifact review traced a lingering admin user + stuck active:true tickets to one gap: tools/compliance_rbac_jit.py audit is the only revocation path for expired JIT grants — and nothing ran it on a schedule. The tool fixes (idempotent 404 revoke, honest provisioned status) shipped in #111/#85-adjacent work; this closes the operational half.

What

Repo-managed, user-scope scheduling (no root, no /etc changes — safe for a laptop dev host):

  • systemd/localobserve-jit-audit.service + .timer — hourly oneshot cycle, Persistent=true catch-up after downtime; intentionally no cross-manager After=/Wants= (user units cannot order against docker.service; a down stack fails the run safely and the next hour retries)
  • scripts/install-jit-timer.sh — --install / --dry-run / --status / --remove, same REPO_ROOT sed-localization convention as install-logrotate.sh; systemd-analyze verifys generated units
  • Taskfile: install-jit-timer, jit-timer-status, remove-jit-timer
  • Crosswalk Req-3 documentation note
  • tests/test_jit_audit_timer.py — 5 hermetic static guards tying units/installer/Taskfile to the actual tool subcommand

Deliberately excluded

No timer for compliance-ledger-audit: it appends to the VCS-tracked audit_ledger.json, which would keep working trees permanently dirty. Ledger appends stay a change-hygiene step.

Validation

  • bash -n installer; systemd-analyze verify clean on generated units (dry-run, nothing installed)
  • tests/test_jit_audit_timer.py 5/5; full pytest tests/ green
  • Per AGENTS.md: units were verified as generated, but the timer itself was not installed/enabled on this host — that is the reviewer's explicit action (task install-jit-timer)

…er (Req-3)

The 2026-10 review of #82 artifacts found the root-cause gap: the audit
cycle is the ONLY revocation path for expired JIT tickets, and nothing
scheduled it - so an expired security_auditor admin grant had lingered
for months (unrevoked user, tickets stuck active:true).

Adds repo-managed, user-scope scheduling (no root, no /etc):
- systemd/localobserve-jit-audit.service + .timer: hourly oneshot audit
  cycle, Persistent=true for missed-cycle catch-up after downtime;
  deliberately no cross-manager After=/Wants= (user units cannot order
  against docker.service; a down stack fails the run safely and the
  next hour retries).
- scripts/install-jit-timer.sh: install/dry-run/status/remove, reusing
  the install-logrotate.sh REPO_ROOT sed convention; verifies generated
  units with systemd-analyze; documents enable-linger for headless hosts.
- Taskfile: install-jit-timer / jit-timer-status / remove-jit-timer.
- docs/compliance_crosswalk.md Req-3: revocation-scheduling note.
- tests/test_jit_audit_timer.py: 5 hermetic static guards keeping units,
  installer, and Taskfile in sync with the tool subcommand.

Out of scope deliberately: no timer for compliance-ledger-audit - it
appends to the VCS-tracked audit_ledger.json and would keep the working
tree permanently dirty; ledger appends stay a change-hygiene step.
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