secrets-engine/docs/ssh-ca-signing-contract.md
tegwick 3cd9955ac9
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Implement SECRETS-WP-0008 unblocked layer-model obligations
Load pep-stance.yaml as the live unreachable-engine gate and record named
stance fields on privileged evidence. Classify evidence, queue load-bearing
records in a local outbox, and add heartbeat/drain commands that never sit
on a mutation path. Publish proposed SSH-CA and secret-use evidence
contracts without adding an OpenBao SSH-CA write.

T02 (access-engine decision records) and T06 (no standing credential) stay
wait on external endpoints.

Assistant: grok
Assistant-Session: 01a04cea-cb33-7c63-bad7-c1b0f9f0076b
2026-08-29 12:52:55 +02:00

3.7 KiB

SSH-CA signing engine contract (proposed)

Status: proposed. layer.yaml owner_status remains proposed until this surface ships. ops-warden must assent or contest before any replacement client is written.

Standard: NetKingdom Security Layer Model v0.7 §3.3 (Lifecycle), §6.4 (PEP). Companion: net-kingdom/SECURITY-COMPANION.md.

What this is

A deterministic Lifecycle engine API that asks OpenBao to sign a short-lived SSH user certificate after an access-engine decision record naming the request. secrets-engine presents no additional authority of its own beyond the decision-bound role. The action reconstructs as the caller's.

What this is not

  • Operational ownership of the SSH access lane. warden sign, cert_command, and host-access stewardship stay with ops-warden (Staff PEP).
  • A break-glass AppRole. The cataloged standalone warden-sign AppRole stays parked.
  • An authorization decision, an approval store, or a second PDP.
  • A writer of private keys. The caller supplies the public key; the engine returns only the signed certificate material through a scoped delivery path.

Caller

ops-warden, after it holds an access-engine decision for the sign request, or after it has recorded the application of its own published unreachable-engine stance in place of a decision (pep-stance.yaml in ops-warden).

Request

Field Meaning
actor_type adm | agt | atm
actor_name Attributable principal the certificate is issued for
identity Certificate key id / identity string
principals Exact principal list; no wildcards
public_key Caller-supplied public key (not a private key)
ttl Requested lifetime; engine enforces the actor-type maximum
decision_id Access-engine decision record id, present only where a decision was rendered
request_digest Canonical digest of subject, action, resource, context
stance Named unreachable-engine residue if no decision was rendered

Replay is permitted iff the canonical request digest matches and the decision lifetime holds. A different resource is a different request.

Response (non-secret)

Field Meaning
signed Whether OpenBao signed
valid_before Certificate expiry
role OpenBao SSH role used (agt-role / adm-role / atm-role)
decision_id Echoed when present
evidence_id Local non-secret evidence record id

Certificate private material never appears in this response, in evidence, or in argv. Delivery of the signed certificate uses a scoped file or exec path with mode 0600, outside Git, same rules as existing handoff.

Lifetime

Every allow has an explicit end: the certificate TTL, bounded by actor-type maxima already documented on the warden-sign lane. No standing grant.

Evidence

Attributive unless a future control branches on the presence of a signing record — today none does. Completeness is not claimed. Records may include actor type, role, valid_before, decision id, and stance fields. They must never include a public-key blob if it could identify a live private key handle, a token, or certificate private material.

Destination today: local JSONL. Intended destination: audit-core.

Non-responsibilities

secrets-engine does not choose principals, mint SSH keys, open tunnels, log into hosts, or override ops-warden's zone stance map. If access-engine is unreachable, this engine applies its own published catalog-stage stance (pep-stance.yaml in this repository) and does not consult ops-warden's map.

Assent

A coordination message to ops-warden records this contract. Assent or contest belongs in ops-warden's own voice. Until then no OpenBao SSH-CA write is added to the secrets-engine CLI.