Files
flex-auth/workplans/FLEX-WP-0006-ops-warden-ssh-signing-policy-gate.md
tegwick 0fde95a87c
Some checks failed
CI / Build and Test (push) Has been cancelled
CI / Lint (push) Has been cancelled
FLEX-WP-0006: implement ops-warden signing gate policy
2026-06-23 21:17:42 +02:00

7.8 KiB

id, type, title, domain, repo, status, owner, topic_slug, planning_priority, planning_order, depends_on_workplans, related_workplans, created, updated, state_hub_workstream_id
id type title domain repo status owner topic_slug planning_priority planning_order depends_on_workplans related_workplans created updated state_hub_workstream_id
FLEX-WP-0006 workplan Ops-Warden SSH Signing Policy Gate infotech flex-auth finished codex flex-auth P0 60
FLEX-WP-0002
FLEX-WP-0005
WARDEN-WP-0009
2026-06-23 2026-06-23 bbea4049-8acc-4d7c-8cf5-3106c6b93f7f

FLEX-WP-0006: Ops-Warden SSH Signing Policy Gate

Purpose

Publish the flex-auth policy package, registry fixtures, and service contract evidence needed for ops-warden's opt-in pre-sign gate.

Ops-warden already shipped the caller side in WARDEN-WP-0007: policy.enabled: true makes warden sign and local-backend warden issue call POST /v1/check before signing. Production OpenBao-backed signing was verified in WARDEN-WP-0008. The remaining blocked work is flex-auth-owned: policies for resource.type: ssh-certificate and action: sign.

This workplan unblocks ops-warden/workplans/WARDEN-WP-0009-flex-auth-policy-gate-production.md.

Gate Contract

The shipped ops-warden gate sends this flex-auth decision request:

Field Meaning
subject.id WARDEN_POLICY_SUBJECT when set, otherwise actor name
subject.type Actor type: adm, agt, or atm
tenant policy.tenant, default tenant:platform
resource.id ssh-cert:actor/<actor-name>
resource.type ssh-certificate
resource.system ops-warden
action sign
context.principals Requested SSH certificate principals from inventory
context.actor_type Actor type: adm, agt, or atm
context.pubkey_fingerprint SHA256 fingerprint of the submitted public key text
context.ttl_hours Requested certificate TTL

Allow responses must return effect: allow plus a decision id or request_id; ops-warden records that value as policy_decision_id in signatures.log. Deny responses must include a human-readable reason that the ops-warden CLI can surface.

Policy Boundary

flex-auth decides whether this specific signing request is allowed now. ops-warden remains responsible for SSH CA operation, OpenBao integration, actor inventory, host documentation, and local scorecard checks.

The flex-auth policy must not request or store SSH private keys, OpenBao tokens, database credentials, or other secrets. Acceptance evidence should use fixtures, non-secret request bodies, decision ids, and sanitized logs only.

T1 - Pin the ops-warden protected-system contract

id: FLEX-WP-0006-T01
status: done
priority: high
state_hub_task_id: "8831b904-dbef-4d55-8eb5-053c939c86b3"

Add an ops-warden protected-system manifest and registry fixture slice that declares:

  • protected system ops-warden
  • resource type ssh-certificate
  • action sign
  • tenant tenant:platform
  • supported actor subject types adm, agt, and atm
  • required context fields: principals, actor_type, pubkey_fingerprint, and ttl_hours

Output should live under examples/ops-warden/ unless implementation reveals a more idiomatic local path. The manifest and fixture must validate with the existing flex-auth validate and flex-auth load-registry commands.

T2 - Author the ssh-certificate sign policy package

id: FLEX-WP-0006-T02
status: done
priority: high
state_hub_task_id: "9ea206fa-f93d-46b6-8b8e-e8669dd502d4"

Create the Rego-in-Markdown policy package for ops-warden signing decisions.

Minimum allow criteria:

  • request action is sign
  • resource system is ops-warden
  • resource type is ssh-certificate
  • tenant is tenant:platform unless the fixture explicitly tests another configured tenant
  • subject and context.actor_type are aligned with the actor resource
  • requested TTL is positive and within the policy's configured maximum for the actor type
  • requested principals are non-empty and allowed for the actor fixture
  • context.pubkey_fingerprint is present

Minimum deny criteria:

  • unknown subject or actor resource
  • mismatched subject.type, context.actor_type, or resource.id: ssh-cert:actor/<actor>
  • TTL outside policy bounds
  • missing fingerprint
  • disallowed or empty principals
  • wrong action, system, resource type, or tenant

The package should produce clear deny reasons and preserve the standard decision envelope so ops-warden can surface reason without special casing.

T3 - Add allow and deny fixtures

id: FLEX-WP-0006-T03
status: done
priority: high
state_hub_task_id: "6bf5cb9b-d46c-49cf-aec0-12f6e864a1f8"

Add fixture requests and expected decisions for the gate.

Required fixtures:

  • allow: valid adm sign request
  • allow: valid agt sign request, if an agent actor fixture exists
  • deny: unknown subject
  • deny: actor type mismatch
  • deny: TTL above policy max
  • deny: missing or disallowed principal
  • deny: missing pubkey_fingerprint

Wire the fixtures into Go tests or the existing policy fixture runner so make test proves the package behavior. Fixture data must remain non-secret.

T4 - Verify the /v1/check service contract

id: FLEX-WP-0006-T04
status: done
priority: high
state_hub_task_id: "077d29db-30e0-4447-90fd-620c0884306c"

Run flex-auth serve with the ops-warden registry and policy package, then exercise POST /v1/check with ops-warden-shaped JSON.

Acceptance evidence:

  • allow response includes effect: allow and a stable decision id
  • deny response includes effect: deny and a useful reason
  • decision log records the allow and deny decisions without secrets
  • method mismatch and malformed JSON fail predictably
  • the documented behavior is compatible with ops-warden fail_closed: true

If the current service shape needs a small compatibility adjustment, keep it inside the stable v1 API instead of adding an ops-warden-specific route.

T5 - Hand off production-readiness evidence to ops-warden

id: FLEX-WP-0006-T05
status: done
priority: medium
state_hub_task_id: "06cac0b1-51c0-4ae0-b605-c940f7821ac7"

Publish the handoff notes ops-warden needs to close WARDEN-WP-0009 T01 and start its production enablement smoke.

Include:

  • policy package path and version
  • registry fixture path
  • local service command
  • allow and deny fixture names
  • non-secret decision ids from local smoke
  • expected policy.enabled production sequence
  • reminder that OpenBao SSH signing and SSH CA custody remain ops-warden-owned

Record progress in State Hub and ask the custodian operator to run make fix-consistency REPO=flex-auth from ~/state-hub after this workplan is merged or otherwise accepted.

Implementation Summary

Implemented on 2026-06-23.

  • Added examples/ops-warden/ with the protected-system manifest, subject and resource manifests, combined registry snapshot, policy package, check requests, and allow/deny fixtures.
  • Added top-level tenant support to CheckRequest and BatchCheckRequest so the shipped ops-warden policy gate request shape is accepted by /v1/check.
  • Added CLI and HTTP service tests for the ops-warden allow path, deny path, malformed JSON, method mismatch, and decision-log recording.
  • Added docs/ops-warden-policy-gate-handoff.md with non-secret smoke evidence and the ops-warden production enablement sequence.

Exit Criteria

  • flex-auth contains a validated ops-warden protected-system manifest and registry fixture.
  • flex-auth contains an ssh-certificate / sign policy package with allow and deny fixtures for adm, agt, and atm-style actors where applicable.
  • make test passes.
  • POST /v1/check accepts the shipped ops-warden request shape and returns decision envelopes compatible with policy.enabled: true.
  • A sanitized handoff note exists for ops-warden WARDEN-WP-0009.
  • State Hub progress is logged and the operator is told to run make fix-consistency REPO=flex-auth.