Record Policy Nexus metadata apply and diagnose bootstrap
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
parent
1d5f35539d
commit
a6d47c51cc
3 changed files with 46 additions and 2 deletions
|
|
@ -3,7 +3,7 @@ kind: credential-change-request
|
||||||
schema_version: 1
|
schema_version: 1
|
||||||
request_type: workload-kv-read
|
request_type: workload-kv-read
|
||||||
title: Policy Nexus Forgejo private-source read token lane
|
title: Policy Nexus Forgejo private-source read token lane
|
||||||
status: approved
|
status: applied
|
||||||
created: '2026-08-31'
|
created: '2026-08-31'
|
||||||
updated: '2026-08-31'
|
updated: '2026-08-31'
|
||||||
requester:
|
requester:
|
||||||
|
|
@ -137,6 +137,16 @@ verification:
|
||||||
and its public health endpoint returns 200; the KeyCape openbao-admin authorize
|
and its public health endpoint returns 200; the KeyCape openbao-admin authorize
|
||||||
path returns 302. No Forgejo identity, PAT, OpenBao secret value, Actions secret,
|
path returns 302. No Forgejo identity, PAT, OpenBao secret value, Actions secret,
|
||||||
or workflow run was created.
|
or workflow run was created.
|
||||||
|
- at: '2026-08-31T22:15:50+00:00'
|
||||||
|
actor: attended operator via governed platform-admin lane
|
||||||
|
kind: delegated_metadata_apply
|
||||||
|
result: passed
|
||||||
|
details:
|
||||||
|
- Delegated metadata applier ran as attended operator via governed platform-admin
|
||||||
|
lane using local bao CLI ambient authority.
|
||||||
|
- 'Policy metadata write: sys/policies/acl/workload-kv-read-policy-nexus-forgejo-source'
|
||||||
|
- 'Auth role metadata write: auth/netkingdom/role/policy-nexus-forgejo-source-workload-kv-read'
|
||||||
|
- No secret values were read, written, printed, or accepted in argv.
|
||||||
lifecycle:
|
lifecycle:
|
||||||
deactivate: Remove the repository Actions secret, revoke the Forgejo PAT, disable
|
deactivate: Remove the repository Actions secret, revoke the Forgejo PAT, disable
|
||||||
the OpenBao access path, and leave scheduled publication failing closed.
|
the OpenBao access path, and leave scheduled publication failing closed.
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ SECRET = "FORGEJO_SOURCE_TOKEN"
|
||||||
TOKEN_PREFIX = "policy-nexus-source-read-"
|
TOKEN_PREFIX = "policy-nexus-source-read-"
|
||||||
SCOPES = ["read:repository"]
|
SCOPES = ["read:repository"]
|
||||||
REPO_DIR = Path(__file__).resolve().parent.parent
|
REPO_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
DIAGNOSTIC_PATH = Path("/tmp/policy-nexus-source-bootstrap-diagnostic.json")
|
||||||
NON_CODE_UNITS = (
|
NON_CODE_UNITS = (
|
||||||
"repo.actions",
|
"repo.actions",
|
||||||
"repo.packages",
|
"repo.packages",
|
||||||
|
|
@ -43,6 +44,14 @@ class ProvisionError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def write_diagnostic(stage: str, error: Exception | None = None) -> None:
|
||||||
|
detail = str(error) if isinstance(error, ProvisionError) else "unexpected internal error"
|
||||||
|
DIAGNOSTIC_PATH.write_text(
|
||||||
|
json.dumps({"stage": stage, "detail": detail}, sort_keys=True) + "\n"
|
||||||
|
)
|
||||||
|
DIAGNOSTIC_PATH.chmod(0o600)
|
||||||
|
|
||||||
|
|
||||||
def api_request(
|
def api_request(
|
||||||
token: str,
|
token: str,
|
||||||
method: str,
|
method: str,
|
||||||
|
|
@ -332,6 +341,7 @@ def provision(admin_token: str) -> None:
|
||||||
|
|
||||||
|
|
||||||
def outer() -> int:
|
def outer() -> int:
|
||||||
|
DIAGNOSTIC_PATH.unlink(missing_ok=True)
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[
|
[
|
||||||
"warden",
|
"warden",
|
||||||
|
|
@ -350,6 +360,8 @@ def outer() -> int:
|
||||||
check=False,
|
check=False,
|
||||||
timeout=900,
|
timeout=900,
|
||||||
)
|
)
|
||||||
|
if result.returncode != 0 and not DIAGNOSTIC_PATH.exists():
|
||||||
|
write_diagnostic("forgejo-admin-route")
|
||||||
return result.returncode
|
return result.returncode
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -362,7 +374,12 @@ def main() -> int:
|
||||||
admin_token = os.environ.get("API_TOKEN", "")
|
admin_token = os.environ.get("API_TOKEN", "")
|
||||||
if not admin_token:
|
if not admin_token:
|
||||||
raise ProvisionError("Warden did not provide API_TOKEN")
|
raise ProvisionError("Warden did not provide API_TOKEN")
|
||||||
provision(admin_token)
|
try:
|
||||||
|
provision(admin_token)
|
||||||
|
except Exception as error:
|
||||||
|
write_diagnostic("provision", error)
|
||||||
|
raise
|
||||||
|
DIAGNOSTIC_PATH.unlink(missing_ok=True)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,23 @@ class PolicyNexusForgejoSourceProvisionTests(unittest.TestCase):
|
||||||
MODULE.verify_source_token("candidate", ["read:repository", "write:repository"])
|
MODULE.verify_source_token("candidate", ["read:repository", "write:repository"])
|
||||||
request.assert_not_called()
|
request.assert_not_called()
|
||||||
|
|
||||||
|
def test_diagnostic_redacts_unexpected_exception_details(self) -> None:
|
||||||
|
with self.subTest("unexpected"):
|
||||||
|
with mock.patch.object(MODULE, "DIAGNOSTIC_PATH") as path:
|
||||||
|
MODULE.write_diagnostic("provision", RuntimeError("sensitive detail"))
|
||||||
|
payload = path.write_text.call_args.args[0]
|
||||||
|
self.assertNotIn("sensitive detail", payload)
|
||||||
|
self.assertIn("unexpected internal error", payload)
|
||||||
|
|
||||||
|
with self.subTest("bounded provision error"):
|
||||||
|
with mock.patch.object(MODULE, "DIAGNOSTIC_PATH") as path:
|
||||||
|
MODULE.write_diagnostic(
|
||||||
|
"provision",
|
||||||
|
MODULE.ProvisionError("PUT /bounded/path returned HTTP 403"),
|
||||||
|
)
|
||||||
|
payload = path.write_text.call_args.args[0]
|
||||||
|
self.assertIn("PUT /bounded/path returned HTTP 403", payload)
|
||||||
|
|
||||||
def test_actions_failure_revokes_pat_and_removes_new_kv_value(self) -> None:
|
def test_actions_failure_revokes_pat_and_removes_new_kv_value(self) -> None:
|
||||||
calls: list[tuple[str, str]] = []
|
calls: list[tuple[str, str]] = []
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue