NET-WP-0019: implement T05 (OIDC claims helper + integration in script/console) and T06 (add dry-run to runbook_payloads for web-ui exposure; cross-link update in 0018 T07). Update workplan notes.

This commit is contained in:
2026-06-03 07:10:56 +02:00
parent f56bca5b5d
commit 92bf7d1d1c
4 changed files with 68 additions and 6 deletions

View File

@@ -679,10 +679,11 @@ def print_status(data: dict[str, Any]) -> None:
print("9. lifecycle-guide")
print("10. onboarding-dry-run-template")
print("11. onboarding-dry-run")
print("12. validate-custody-roster")
print("13. metadata-template")
print("14. approve-custody-mode")
print("15. web-ui")
print("12. onboarding-dry-run-claims")
print("13. validate-custody-roster")
print("14. metadata-template")
print("15. approve-custody-mode")
print("16. web-ui")
print("")
print("Refusal boundary")
print("This console will not run bao operator init or collect secret values.")
@@ -1115,6 +1116,34 @@ def print_onboarding_dry_run_template() -> None:
print(json.dumps(onboarding_dry_run_template(), indent=2))
def print_dry_run_oidc_claims_verification(subject: str = "dryrun-user", groups: list[str] | None = None) -> None:
"""T05 helper: non-secret OIDC claims verification for dry-run subject.
Computes expected claims based on LLDAP groups (no secrets).
Used by orchestrator and console 'onboarding-dry-run-claims' .
"""
if groups is None:
groups = ["net-kingdom-users"]
print("OIDC CLAIMS VERIFICATION FOR DRY-RUN (non-secret)")
print(f"Subject: {subject}")
print(f"LLDAP groups (during dry-run): {groups}")
print("")
print("Expected KeyCape OIDC claims (inferred from groups + standard config):")
claims = {
"sub": subject,
"email": f"{subject}@example",
"groups": groups,
"preferred_username": subject,
}
print(json.dumps(claims, indent=2))
print("")
print("OpenBao policy binding (from T01 config): platform-admin role only binds 'net-kingdom-admins' group.")
if "net-kingdom-admins" in groups:
print("WARNING: would grant platform-admin (not for non-root dry-run)")
else:
print("No platform-admin or root authority (correct for non-root).")
print("To verify live: after onboard, use the lifecycle dry-run script which exercises KeyCape verify + LLDAP.")
def print_lifecycle_guide() -> None:
print("NET-WP-0017-T05 LIFECYCLE OPERATOR FLOW GUIDE")
print("")
@@ -2612,6 +2641,15 @@ def runbook_payloads(data: dict[str, Any]) -> list[dict[str, str]]:
},
openbao_downstream_taint if initialized else {},
),
{
"name": "User lifecycle dry-run (T06)",
"description": "Execute non-root onboarding dry-run (create/verify/lock/offboard), check LLDAP/groups/MFA/KeyCape claims, produce evidence. See NET-WP-0019 and dry-run-nonroot-user.sh .",
"subsystem": "LLDAP / privacyIDEA / KeyCape",
"responsibility": "platform-custodian",
"email": role_email(data, "role_platform_custodian_email"),
"location": "sso-mfa/k8s/lldap/dry-run-nonroot-user.sh ; make security-bootstrap-onboarding-dry-run ; console 'onboarding-dry-run' ; NET-WP-0019",
"state": "template",
},
]
@@ -4729,6 +4767,9 @@ def build_parser() -> argparse.ArgumentParser:
sub.add_parser("onboarding-dry-run", help="Run (or guide) a T06 non-root dry-run using the orchestrator script (sso-mfa/k8s/lldap/dry-run-nonroot-user.sh). See NET-WP-0019.")
cl = sub.add_parser("lifecycle-cleanup-dryrun-users", help="Clean up test/dry-run users by pattern (T04 helper, NET-WP-0019). Example: --pattern t06-*")
cl.add_argument("--pattern", default="t06-*", help="Regex or glob pattern for test users to offboard (default t06-*)")
claims = sub.add_parser("onboarding-dry-run-claims", help="T05: Verify expected OIDC claims for a dry-run subject (non-secret, based on groups). See NET-WP-0019-T05.")
claims.add_argument("--subject", default="dryrun-user", help="Test subject username")
claims.add_argument("--groups", default="net-kingdom-users", help="Comma-separated groups during dry-run")
sub.add_parser("handover-checklist", help="Print handover and cleanup checklist.")
sub.add_parser("metadata-template", help="Print non-secret metadata JSON template.")
sub.add_parser("refuse-live-init", help="Explain why live OpenBao init is refused.")
@@ -4829,6 +4870,10 @@ def main(argv: list[str] | None = None) -> int:
script = os.path.abspath(script)
subprocess.call(["bash", script, "--cleanup-only", pat])
return 0
if args.command == "onboarding-dry-run-claims":
groups = getattr(args, "groups", "net-kingdom-users").split(",")
print_dry_run_oidc_claims_verification(getattr(args, "subject", "dryrun-user"), groups)
return 0
if args.command == "handover-checklist":
print_handover_checklist()
return 0