NK-WP-0058-T02 step 2: T15 and T19 exercises run in the contract CI
All checks were successful
Bounded-execution contracts / contracts (push) Successful in 1m16s
Build and Publish bounded-executor / build-and-push (push) Successful in 6s
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
Identity provider journey acceptance / provider (push) Successful in 1m5s
All checks were successful
Bounded-execution contracts / contracts (push) Successful in 1m16s
Build and Publish bounded-executor / build-and-push (push) Successful in 6s
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
Identity provider journey acceptance / provider (push) Successful in 1m5s
T19 runs the KeyCape binary from the pinned image instead of docker: tools/contract-tests/oci_extract.py pulls the image anonymously by digest and verifies manifest and layer digests before extracting. Both exercises record GITHUB_SHA when net-kingdom is a source tarball. PyJWT[crypto] chain pinned by PyPI-checked hashes. 85 tests pass in a CI-like layout. rapp CI recorded (rapp 15df0e3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 943911@bnt-lap001 Assistant-Session: fc322940-1c8e-4bed-ab39-86cec99f23a0
This commit is contained in:
parent
efb68ca36d
commit
79f14ce50a
7 changed files with 190 additions and 13 deletions
|
|
@ -80,7 +80,9 @@ def run(args, timeout=60):
|
|||
|
||||
|
||||
def commit(path: pathlib.Path) -> str:
|
||||
return run(["git", "-C", str(path), "rev-parse", "HEAD"])
|
||||
"""The checkout's commit. In CI net-kingdom is a source tarball: record the commit CI built (GITHUB_SHA)."""
|
||||
done = subprocess.run(["git", "-C", str(path), "rev-parse", "HEAD"], capture_output=True, text=True)
|
||||
return done.stdout.strip() if done.returncode == 0 else os.environ.get("GITHUB_SHA", "not-a-git-checkout")
|
||||
|
||||
|
||||
def private_write(path: pathlib.Path, value: str) -> None:
|
||||
|
|
@ -145,6 +147,7 @@ def exercise(args) -> dict:
|
|||
"target": "disposable local processes; synthetic keys and credentials",
|
||||
"started_at": dt.datetime.now(dt.UTC).isoformat(timespec="seconds"),
|
||||
"keycape_image": KEYCAPE_IMAGE,
|
||||
"keycape_runtime": "binary from the pinned image" if args.keycape_binary else "container",
|
||||
"issuer_contract_commit": commit(args.keycape_source), # key-cape; a "key*" name trips the secret scanner
|
||||
"approval_engine_commit": commit(args.approval_engine_source),
|
||||
"net_kingdom_commit": commit(REPO),
|
||||
|
|
@ -176,6 +179,8 @@ def exercise(args) -> dict:
|
|||
operator = [c for c in examples if c["clientId"] == OPERATOR]
|
||||
assert len(operator) == 1
|
||||
config.update(issuer=issuer, clients=[client, operator[0]])
|
||||
if args.keycape_binary: # no container: the binary reads its files from the temporary folder directly
|
||||
config.update(port=port, privateKeyPem=str(root / "key.pem"))
|
||||
config["authelia"]["issuer"] = "https://synthetic-upstream.invalid"
|
||||
private_write(root / "config.yaml", yaml.safe_dump(config, sort_keys=False))
|
||||
values = {c["clientId"]: secrets.token_urlsafe(48) for c in (client, operator[0])}
|
||||
|
|
@ -183,13 +188,20 @@ def exercise(args) -> dict:
|
|||
c["secretRef"].removeprefix("env:") + "=" + values[c["clientId"]] + "\n" for c in (client, operator[0])))
|
||||
os.chmod(root, 0o755) # the container user reads the bind mount
|
||||
container = "nk56-t19-keycape-" + secrets.token_hex(5)
|
||||
created = engine = api_server = None
|
||||
created = engine = api_server = process = None
|
||||
try:
|
||||
run(["docker", "run", "-d", "--rm", "--pull=never", "--name", container, "--user", str(os.getuid()),
|
||||
"--read-only", "--cap-drop=ALL", "--security-opt=no-new-privileges",
|
||||
"--publish", f"127.0.0.1:{port}:8080", "--env-file", str(root / "env"),
|
||||
"--mount", f"type=bind,source={temporary},target=/etc/keycape,readonly", KEYCAPE_IMAGE])
|
||||
created = True
|
||||
if args.keycape_binary:
|
||||
# the binary extracted from KEYCAPE_IMAGE by tools/contract-tests/oci_extract.py (digest-verified)
|
||||
env = {"PATH": "/usr/bin:/bin", "KEYCAPE_CONFIG": str(root / "config.yaml"),
|
||||
**{c["secretRef"].removeprefix("env:"): values[c["clientId"]] for c in (client, operator[0])}}
|
||||
process = subprocess.Popen([str(args.keycape_binary)], env=env, cwd=temporary,
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
else:
|
||||
run(["docker", "run", "-d", "--rm", "--pull=never", "--name", container, "--user", str(os.getuid()),
|
||||
"--read-only", "--cap-drop=ALL", "--security-opt=no-new-privileges",
|
||||
"--publish", f"127.0.0.1:{port}:8080", "--env-file", str(root / "env"),
|
||||
"--mount", f"type=bind,source={temporary},target=/etc/keycape,readonly", KEYCAPE_IMAGE])
|
||||
created = True
|
||||
for _ in range(80):
|
||||
try:
|
||||
with urllib.request.urlopen(issuer + "/jwks", timeout=1) as response:
|
||||
|
|
@ -353,6 +365,9 @@ def exercise(args) -> dict:
|
|||
engine.close()
|
||||
if created:
|
||||
run(["docker", "stop", "--time=5", container])
|
||||
if process:
|
||||
process.terminate()
|
||||
process.wait(timeout=10)
|
||||
|
||||
receipt.update(status="passed", cleanup_complete=True,
|
||||
finished_at=dt.datetime.now(dt.UTC).isoformat(timespec="seconds"))
|
||||
|
|
@ -368,6 +383,8 @@ def main(argv=None) -> int:
|
|||
parser.add_argument("--keycape-source", type=pathlib.Path, default=home / "key-cape")
|
||||
parser.add_argument("--approval-engine-source", type=pathlib.Path, default=home / "approval-engine")
|
||||
parser.add_argument("--receipt", required=True, type=pathlib.Path)
|
||||
parser.add_argument("--keycape-binary", type=pathlib.Path,
|
||||
help="run this KeyCape binary (extracted from the pinned image) instead of docker (CI)")
|
||||
parser.add_argument("--trace", action="store_true", help="print the failing assertion's location (no values)")
|
||||
args = parser.parse_args(argv)
|
||||
if args.receipt.exists():
|
||||
|
|
|
|||
|
|
@ -59,8 +59,9 @@ C = _load("clients", HERE / "clients.py")
|
|||
|
||||
|
||||
def commit(path: pathlib.Path) -> str:
|
||||
return subprocess.run(["git", "-C", str(path), "rev-parse", "HEAD"], capture_output=True, text=True,
|
||||
check=True).stdout.strip()
|
||||
"""The checkout's commit. In CI net-kingdom is a source tarball: record the commit CI built (GITHUB_SHA)."""
|
||||
done = subprocess.run(["git", "-C", str(path), "rev-parse", "HEAD"], capture_output=True, text=True)
|
||||
return done.stdout.strip() if done.returncode == 0 else os.environ.get("GITHUB_SHA", "not-a-git-checkout")
|
||||
|
||||
|
||||
def private_write(path: pathlib.Path, value: str) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue