NK-WP-0056-T06: executor waits for every endpoint; errors named by phase, never mislabelled as no-effect
All checks were successful
All checks were successful
Two live runs of BEA-2026-0002 ended setup:URLError while four read-only diagnostic pods (same image, labels, mounts and config) reached every endpoint. Likely cause: a fresh Job pod reaches OpenBao before the sso/approval-engine ingress rules admit it (NetworkPolicy is programmed per destination). Now: - build waits until OpenBao, KeyCape, approval-engine, audit-core and LLDAP all answer HTTP (one shared 30 s budget); an unreachable one is named: setup:<name> not reachable. - a preflight error is a refusal named preflight_error:<Type> (preflight has no effect). - an error in the consume read-back is outcome unknown, consume_unconfirmed:<Type>, alerted; before, any exception after setup was reported as 'refused, no effect' even after consume. - any other escaping error after setup is outcome unknown (exit 5), never 'no effect'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 523928@bnt-lap001 Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350
This commit is contained in:
parent
a962bc8ecc
commit
c2a0f2f4e0
5 changed files with 116 additions and 9 deletions
|
|
@ -54,6 +54,7 @@ import pathlib
|
|||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import urllib.parse
|
||||
|
||||
HERE = pathlib.Path(__file__).resolve().parent
|
||||
|
||||
|
|
@ -106,6 +107,19 @@ def distinct_roles(cfg: dict) -> None:
|
|||
raise ValueError("every lane must use its own OpenBao role")
|
||||
|
||||
|
||||
def run_endpoints(cfg: dict) -> dict:
|
||||
"""Every service the run talks to, with a path that answers HTTP without credentials (any status counts)."""
|
||||
ends = {"openbao": (cfg["openbao"]["addr"], "/v1/sys/health"),
|
||||
"lldap": (cfg["lldap"]["url"], "/"),
|
||||
"audit-core": (cfg["audit_core"]["url"], "/healthz"),
|
||||
"approval-engine": (cfg["approval_engine"]["url"], "/healthz")}
|
||||
client = cfg["approval_engine"].get("client")
|
||||
if client: # the KeyCape token endpoint answers a GET with an HTTP error, which proves the path
|
||||
token = urllib.parse.urlsplit(client["token_url"])
|
||||
ends["keycape"] = (f"{token.scheme}://{token.netloc}", "/healthz")
|
||||
return ends
|
||||
|
||||
|
||||
def build(cfg: dict, logins: list):
|
||||
"""`logins` collects every OpenBao client as soon as it exists, so the caller revokes them all, even when a
|
||||
later step of setup fails."""
|
||||
|
|
@ -114,7 +128,7 @@ def build(cfg: dict, logins: list):
|
|||
raise ValueError("the journey read and the bind write must use separate roles")
|
||||
distinct_roles(cfg)
|
||||
|
||||
OPS.wait_reachable(o["addr"], ca_file=o.get("ca_file")) # new pod: NetworkPolicy may not be applied yet
|
||||
OPS.wait_all_reachable(run_endpoints(cfg)) # new pod: NetworkPolicy is programmed per destination
|
||||
|
||||
def login(role: str):
|
||||
client = OPS.OpenBao(o["addr"], k8s_role=role, jwt_file=o["jwt_file"], ca_file=o.get("ca_file"))
|
||||
|
|
@ -336,9 +350,16 @@ def main(argv=None) -> int:
|
|||
logins: list = []
|
||||
try:
|
||||
config, deps = build(cfg, logins)
|
||||
result = X.Run(admission, args.approval_id, config, deps).execute()
|
||||
except Exception as error: # setup failed before preflight: nothing was consumed
|
||||
result = {"outcome": "refused", "reason": "setup:" + type(error).__name__, "run_id": None, "effects": False}
|
||||
where = str(error) if isinstance(error, OPS.Unreachable) else type(error).__name__
|
||||
result = {"outcome": "refused", "reason": "setup:" + where, "run_id": None, "effects": False}
|
||||
else:
|
||||
run = X.Run(admission, args.approval_id, config, deps)
|
||||
try:
|
||||
result = run.execute() # labels its own preflight and consume errors
|
||||
except Exception as error: # anything else after setup: the run's effect is not established
|
||||
result = {"outcome": "unknown", "reason": "run:" + type(error).__name__, "run_id": run.run_id,
|
||||
"effects": "unknown"}
|
||||
finally:
|
||||
for client in logins:
|
||||
client.revoke_self()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue