feat: declare proposed fixed KeyCape issuer ESO source contract
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1468b-63fa-7710-85dc-8f2e16b3ebfa
This commit is contained in:
codex 2026-10-17 20:36:52 +02:00
parent 0a9617a62d
commit 104ed90f42
4 changed files with 313 additions and 0 deletions

View file

@ -0,0 +1,68 @@
# Proposed fixed issuer ESO contract — RPF-1.3-T4 / NK48-R5-F2
Status: proposed source; not admitted, deployed, or owner-acknowledged. This is a
new Platform declaration for review, not an existing Forgejo grant discovery.
The only substitution in `manifests/templates/keycape-issuer-eso.yaml`
(sha256:e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743) is the admitted `client_id`. The proposed issuer
store is **ClusterSecretStore `openbao-keycape-{client_id}-issuer`**, cluster
scoped (no metadata namespace), restricted by conditions to ExternalSecrets in
`sso`. For Forgejo it is `openbao-keycape-forgejo-issuer`. The suffix makes the
issuer purpose explicit and keeps type-admitted IDs ending in `-` representable.
The store's DNS subdomain name can exceed 63 characters; the existing adapter's
63-character target Secret reference bound is preserved (client ID at most 48).
No type parameter is added or changed.
The provider is `http://openbao.openbao.svc:8200`, KV v2 mount `platform`,
Kubernetes auth mount `kubernetes`, role `external-secrets-keycape-{client_id}`,
serviceAccountRef `external-secrets/external-secrets`, audience `openbao`.
CCR-2026-0041 already records that Forgejo role/identity/audience, not this new
store name or an unrestricted client family grant. Other clients still require
their own existing owner-controlled role/case admission.
The ExternalSecret is `sso/keycape-{client_id}-client`, references precisely that
ClusterSecretStore, refreshes every 5m and targets the same name with Owner
creation and Retain remote deletion. Its only data entry maps `client-secret`
from remoteRef `workloads/keycape/{client_id}`, property `CLIENT_SECRET`. The
provider mount plus mount-relative remoteRef equals custody reference
`platform/workloads/keycape/{client_id}`; do not double-prefix `platform/`.
This is distinct from the Apps-owned consumer namespace SecretStore
`openbao-keycape-{client_id}-consumer` and its dedicated consumer identity.
Store provisioning belongs to Platform's separate owner-controlled path. The
proposed `platform-secret-delivery` lane retains ONLY create/get/watch/delete on
the exact ExternalSecret in `sso`; this source does not delegate store creation
or Secret read/list. Never apply the multi-document template through that lane.
The pure `scripts/keycape_issuer_eso.py` module exposes only the ExternalSecret
document through `external_secret()` and validates fixed public observations
through `require_fixed_store()` and `require_ready_delivery()`. It performs no
API call and issues no evidence/receipt. It is not a real capability or admission
boundary; a caller-supplied observation alone establishes no authenticity.
The existing RPF-1.3-T4 delivery binding must validate the case/client binding,
verify this exact preexisting store's public identity/spec/Ready state, apply or
compare the exact ExternalSecret, and wait for matching spec plus Ready=True.
The proposed helper accepts extra controller metadata but deliberately refuses
spec drift. Actual API defaulting/normalization and installed ESO schema support
must be checked in that implementation; these fixtures establish no native
compatibility or credential isolation. ESO's shared controller remains trusted.
No Secret bodies, values, arbitrary remoteRefs, or raw errors may enter receipts.
Existing owner requirements remain: closed `netkingdom.deliver-secret.v1`
metadata receipt with authenticated before/after UID/resourceVersion provenance,
unchanged objects reported NO_CHANGE, attempt-session revocation, and created-only
rollback guarded by exact UID/resourceVersion (drift or uncertain ownership goes
to owner reconciliation). The helper neither deletes a target Secret nor creates
an OpenBao role/policy nor changes CCR-0041. These capabilities and catalog routing
remain unimplemented/unaccepted under RPF-1.3-T4. Independent Platform source
review of this declaration precedes adopting the conditional NetKingdom type
text; no descriptor acceptance, acknowledgment, pin, grant, catalog or native
permission is inferred.
Grounding: CCR-2026-0041 exact role/identity; the approved historical
`docs/provisioning-windows/2026-10-04-1000/keycape/eso.draft.yaml` issuer
ClusterSecretStore and target pattern; `scripts/catalog_lane_scaffold.py`
ClusterSecretStore/namespace restriction and mount-relative remoteRef model;
RPF-1.3-C1 and RPF-1.3-T4 in the frozen owner review. The scaffold's historical
audience field placement differs from the issuer draft; this candidate uses
the issuer draft's serviceAccountRef.audiences, not a claim of installed support.

View file

@ -0,0 +1,46 @@
# PROPOSED SOURCE ONLY — RPF-1.3-T4 / NK48-R5-F2; not admitted or applied.
# Platform controls this template. Only admitted client_id is substituted.
# Provision the store through Platform's separate reviewed owner path; the
# platform-secret-delivery lane applies ONLY the ExternalSecret document.
apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: openbao-keycape-{client_id}-issuer
spec:
provider:
vault:
server: http://openbao.openbao.svc:8200
path: platform
version: v2
auth:
kubernetes:
mountPath: kubernetes
role: external-secrets-keycape-{client_id}
serviceAccountRef:
name: external-secrets
namespace: external-secrets
audiences:
- openbao
conditions:
- namespaces:
- sso
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: keycape-{client_id}-client
namespace: sso
spec:
refreshInterval: 5m
secretStoreRef:
kind: ClusterSecretStore
name: openbao-keycape-{client_id}-issuer
target:
name: keycape-{client_id}-client
creationPolicy: Owner
deletionPolicy: Retain
data:
- secretKey: client-secret
remoteRef:
key: workloads/keycape/{client_id}
property: CLIENT_SECRET

View file

@ -0,0 +1,70 @@
"""Proposed fixed issuer ESO source contract for RPF-1.3-T4 / NK48-R5-F2.
Pure public metadata only. No API/credential/Secret access or apply path. This
new declaration requires independent Platform review before type integration.
The delivery lane may use only external_secret(); store provisioning is a
separate owner action and is never delegated by this module.
"""
from __future__ import annotations
from copy import deepcopy
from pathlib import Path
import re
import yaml
ROOT = Path(__file__).resolve().parents[1]
TEMPLATE = ROOT / 'manifests/templates/keycape-issuer-eso.yaml'
class Refused(ValueError):
"""Fixed issuer metadata differs; never return an owner delivery receipt."""
def documents(client_id: str) -> tuple[dict, dict]:
# Match the frozen type client_id pattern and existing adapter's derived bound.
# No caller can supply a store name/kind/namespace or an OpenBao path.
if not isinstance(client_id, str) or not re.fullmatch(r'[a-z0-9][a-z0-9-]{1,62}', client_id):
raise Refused('bounded admitted client_id required')
if len('keycape-' + client_id + '-client') > 63:
raise Refused('derived issuer reference exceeds existing adapter bound')
store, external = yaml.safe_load_all(TEMPLATE.read_text().format(client_id=client_id))
return store, external
def external_secret(client_id: str) -> dict:
"""The ONLY document the proposed delivery capability may apply."""
return deepcopy(documents(client_id)[1])
def _matching_public_resource(observed: dict, expected: dict) -> None:
if not isinstance(observed, dict):
raise Refused('public resource observation required')
metadata = observed.get('metadata')
if not isinstance(metadata, dict):
raise Refused('resource metadata required')
expected_namespace = expected['metadata'].get('namespace')
namespace_matches = (metadata.get('namespace') == expected_namespace
if expected_namespace else metadata.get('namespace') in (None, ''))
if (observed.get('apiVersion') != expected['apiVersion']
or observed.get('kind') != expected['kind']
or metadata.get('name') != expected['metadata']['name']
or not namespace_matches
or observed.get('spec') != expected['spec']):
raise Refused('fixed issuer resource differs')
status = observed.get('status')
conditions = status.get('conditions', []) if isinstance(status, dict) else []
if not isinstance(conditions, list) or not any(
isinstance(c, dict) and c.get('type') == 'Ready' and c.get('status') == 'True'
for c in conditions):
raise Refused('fixed issuer resource not ready')
def require_fixed_store(observed: dict, client_id: str) -> None:
"""Refuse a missing/drifted/not-ready store; never create it through delivery."""
_matching_public_resource(observed, documents(client_id)[0])
def require_ready_delivery(observed: dict, client_id: str) -> None:
"""Spec equality and Ready precede a created/NO_CHANGE owner receipt."""
_matching_public_resource(observed, documents(client_id)[1])

View file

@ -0,0 +1,129 @@
"""Public metadata fixtures only: no API, credentials, or native calls."""
import copy
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
import keycape_issuer_eso as contract
class FixedIssuerContract(unittest.TestCase):
def observations(self):
resources = contract.documents("forgejo")
for resource in resources:
resource["metadata"].update(uid="public-fixture-uid", resourceVersion="7")
resource["status"] = {"conditions": [{"type": "Ready", "status": "True"}]}
return resources
def test_independent_forgejo_binding(self):
# Independent owner-source example: CCR0041 role/SA/audience and the
# existing issuer ESO draft's provider/target/relative key convention.
store, external = contract.documents("forgejo")
self.assertEqual(store["kind"], "ClusterSecretStore")
self.assertEqual(store["metadata"], {"name": "openbao-keycape-forgejo-issuer"})
self.assertEqual(store["spec"], {
"provider": {"vault": {
"server": "http://openbao.openbao.svc:8200", "path": "platform", "version": "v2",
"auth": {"kubernetes": {"mountPath": "kubernetes",
"role": "external-secrets-keycape-forgejo",
"serviceAccountRef": {"name": "external-secrets", "namespace": "external-secrets",
"audiences": ["openbao"]}}}}},
"conditions": [{"namespaces": ["sso"]}]})
self.assertEqual(external["metadata"], {"name": "keycape-forgejo-client", "namespace": "sso"})
self.assertEqual(external["spec"], {
"refreshInterval": "5m",
"secretStoreRef": {"kind": "ClusterSecretStore", "name": "openbao-keycape-forgejo-issuer"},
"target": {"name": "keycape-forgejo-client", "creationPolicy": "Owner", "deletionPolicy": "Retain"},
"data": [{"secretKey": "client-secret", "remoteRef": {
"key": "workloads/keycape/forgejo", "property": "CLIENT_SECRET"}}]})
def test_valid_ready_metadata_allows_extra_controller_metadata(self):
store, external = self.observations()
contract.require_fixed_store(store, "forgejo")
contract.require_ready_delivery(external, "forgejo")
def test_store_drift_refuses(self):
changes = [
("kind", "SecretStore"),
("metadata.namespace", "sso"),
("metadata.name", "caller-store"),
("spec.provider.vault.server", "https://wrong.invalid"),
("spec.provider.vault.path", "tenant"),
("spec.provider.vault.auth.kubernetes.role", "external-secrets-keycape-sibling"),
("spec.provider.vault.auth.kubernetes.serviceAccountRef.audiences", ["wrong"]),
("spec.provider.vault.auth.kubernetes.serviceAccountRef.namespace", "sso"),
("spec.conditions", [{"namespaces": ["sso", "other"]}]),
]
for path, value in changes:
with self.subTest(path=path):
store = self.observations()[0]
mutate(store, path, value)
with self.assertRaises(contract.Refused):
contract.require_fixed_store(store, "forgejo")
def test_external_drift_refuses(self):
changes = [
("metadata.namespace", ""), ("metadata.namespace", None), ("metadata.namespace", "other"),
("metadata.name", "keycape-sibling-client"),
("spec.secretStoreRef.kind", "SecretStore"),
("spec.secretStoreRef.name", "openbao-keycape-forgejo-consumer"),
("spec.target.name", "other"), ("spec.target.creationPolicy", "Merge"),
("spec.target.deletionPolicy", "Delete"),
("spec.data", [{"secretKey": "client-secret", "remoteRef": {
"key": "platform/workloads/keycape/forgejo", "property": "CLIENT_SECRET"}}]),
("spec.data", [{"secretKey": "wrong", "remoteRef": {
"key": "workloads/keycape/forgejo", "property": "CLIENT_SECRET"}}]),
("spec.data", [{"secretKey": "client-secret", "remoteRef": {
"key": "workloads/keycape/forgejo", "property": "wrong"}}]),
]
for path, value in changes:
with self.subTest(path=path, value=value):
external = self.observations()[1]
mutate(external, path, value)
with self.assertRaises(contract.Refused):
contract.require_ready_delivery(external, "forgejo")
def test_missing_or_unready_refuses(self):
for check, index in [(contract.require_fixed_store, 0), (contract.require_ready_delivery, 1)]:
for status in [None, {}, [], "bad", {"conditions": None},
{"conditions": [{"type": "Ready", "status": "False"}]}]:
with self.subTest(check=check.__name__, status=status):
observed = self.observations()[index]
observed["status"] = status
with self.assertRaises(contract.Refused):
check(observed, "forgejo")
for malformed in [None, [], {}, {"metadata": None}]:
with self.assertRaises(contract.Refused):
check(malformed, "forgejo")
def test_no_caller_store_or_path_override(self):
for invalid in ["", "f", "../forgejo", "forgejo/sibling", "Forgejo", "forgejo\n", "-forgejo", "f" * 49, None]:
with self.subTest(invalid=invalid), self.assertRaises(contract.Refused):
contract.documents(invalid)
with self.assertRaises(TypeError):
contract.external_secret("forgejo", store_name="caller-store")
def test_type_admitted_trailing_dash_is_preserved(self):
self.assertEqual(contract.external_secret("forgejo-")["metadata"]["name"],
"keycape-forgejo--client")
self.assertEqual(contract.documents("forgejo-")[0]["metadata"]["name"],
"openbao-keycape-forgejo--issuer")
def test_delivery_document_is_only_external_and_detached(self):
external = contract.external_secret("forgejo")
self.assertEqual(external["kind"], "ExternalSecret")
external["spec"]["secretStoreRef"]["name"] = "tampered"
self.assertEqual(contract.external_secret("forgejo")["spec"]["secretStoreRef"]["name"],
"openbao-keycape-forgejo-issuer")
def mutate(resource, path, value):
parts = path.split(".")
for key in parts[:-1]:
resource = resource[key]
resource[parts[-1]] = copy.deepcopy(value)
if __name__ == "__main__":
unittest.main(verbosity=2)