fix(identity): isolate checker environment and executable selection
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
parent
0394484b92
commit
916ba4b33e
4 changed files with 147 additions and 8 deletions
|
|
@ -200,10 +200,10 @@ def deployment_bound(deployment, client):
|
|||
|
||||
def check_config(binary, config_text, env_names, policy_store):
|
||||
"""KeyCape's startup checks on one registry: names and messages only, no values."""
|
||||
command = [binary, 'check-config', '--config', '/dev/stdin', '--env-names', ','.join(env_names)]
|
||||
command = [str(Path(binary).resolve()), 'check-config', '--config', '/dev/stdin', '--env-names', ','.join(env_names)]
|
||||
if policy_store:
|
||||
command.append('--policy-store')
|
||||
result = subprocess.run(command, input=config_text.encode(), capture_output=True, timeout=60)
|
||||
result = subprocess.run(command, input=config_text.encode(), capture_output=True, timeout=60, env={})
|
||||
report = json.loads(result.stdout)
|
||||
require(isinstance(report, dict) and isinstance(report.get('valid'), bool)
|
||||
and report['valid'] == (result.returncode == 0), 'check_config_output_shape')
|
||||
|
|
|
|||
|
|
@ -13,7 +13,12 @@ catalog/acceptance/run-sheet digests and target. The descriptor pins this adapte
|
|||
and its complete local helper import closure together with the exact reviewed
|
||||
`check-config` executable digest. Changing that digest changes the descriptor
|
||||
source pin and descriptor bytes, requiring independently reviewed admission.
|
||||
The fixed executable is rehashed before each attempt. The caller constructs the
|
||||
The fixed executable is rehashed before each attempt. The helper resolves the
|
||||
selected file to an absolute executable path and supplies an empty checker
|
||||
environment, so ambient PATH and KeyCape URL overrides cannot select another
|
||||
executable or alter validation of supplied bytes. Path resolution does not
|
||||
establish immutable storage or eliminate replacement races; executable custody
|
||||
and native runtime admission remain separate requirements. The caller constructs the
|
||||
proposed invocation from exact source inputs, installs the fixed adapter once,
|
||||
and calls normal `Executor.admit`; independently derived admission must match.
|
||||
No callable replacement after admission is required or supported by this recipe.
|
||||
|
|
|
|||
66
sso-mfa/k8s/keycape/test_keycape_checker_environment.py
Normal file
66
sso-mfa/k8s/keycape/test_keycape_checker_environment.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"""Opt-in real-checker boundary regressions; no production inputs or checker stub.
|
||||
|
||||
Set KEYCAPE_TEST_CHECKER_BINARY and KEYCAPE_TEST_CHECKER_SHA256 to an independently
|
||||
built artifact. Ordinary helper-only runs skip this class when none is supplied.
|
||||
"""
|
||||
from contextlib import chdir
|
||||
import hashlib
|
||||
import os
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from test_keycape_client import kc
|
||||
|
||||
VALID = '''issuer: https://issuer.example.invalid
|
||||
port: 8080
|
||||
privateKeyPem: /nonexistent/synthetic-key.pem
|
||||
clients:
|
||||
- clientId: synthetic-client
|
||||
displayName: Synthetic client
|
||||
redirectUris: [https://client.example.invalid/cb]
|
||||
allowedScopes: [openid]
|
||||
grantTypes: [authorization_code]
|
||||
clientType: public
|
||||
'''
|
||||
|
||||
|
||||
class RealCheckerEnvironmentTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
source = os.environ.get('KEYCAPE_TEST_CHECKER_BINARY')
|
||||
if not source:
|
||||
raise unittest.SkipTest('exact real checker artifact not supplied')
|
||||
data = Path(source).read_bytes()
|
||||
expected = os.environ.get('KEYCAPE_TEST_CHECKER_SHA256')
|
||||
if expected != 'sha256:' + hashlib.sha256(data).hexdigest():
|
||||
raise ValueError('real checker artifact digest differs')
|
||||
cls.directory = tempfile.TemporaryDirectory()
|
||||
cls.addClassCleanup(cls.directory.cleanup)
|
||||
cls.binary = Path(cls.directory.name) / 'keycape'
|
||||
cls.binary.write_bytes(data)
|
||||
cls.binary.chmod(0o700)
|
||||
|
||||
def check(self, raw, binary=None):
|
||||
return kc.check_config(str(binary or self.binary), raw, [], False)
|
||||
|
||||
def test_ambient_overrides_cannot_reject_supplied_valid_config(self):
|
||||
with patch.dict(os.environ, {'KEYCAPE_ACCOUNT_PORTAL_URL': 'http://polluted.example.invalid',
|
||||
'KEYCAPE_BROWSER_LOGOUT_URL': 'http://polluted.example.invalid/logout'}):
|
||||
self.assertTrue(self.check(VALID)['valid'])
|
||||
|
||||
def test_ambient_overrides_cannot_admit_supplied_invalid_config(self):
|
||||
invalid = VALID + 'accountPortalURL: http://invalid.example.invalid\nbrowserLogoutURL: http://invalid.example.invalid/logout\n'
|
||||
with patch.dict(os.environ, {'KEYCAPE_ACCOUNT_PORTAL_URL': 'https://polluted.example.invalid',
|
||||
'KEYCAPE_BROWSER_LOGOUT_URL': 'https://polluted.example.invalid/logout'}):
|
||||
self.assertFalse(self.check(invalid)['valid'])
|
||||
|
||||
def test_relative_selected_artifact_is_not_replaced_by_path_decoy(self):
|
||||
decoy = Path(self.directory.name) / 'decoy'
|
||||
decoy.mkdir()
|
||||
trap = decoy / 'keycape'
|
||||
trap.write_text('#!/bin/sh\nexit 27\n')
|
||||
trap.chmod(0o700)
|
||||
with chdir(self.directory.name), patch.dict(os.environ, {'PATH': str(decoy)}):
|
||||
self.assertTrue(self.check(VALID, binary=Path('keycape'))['valid'])
|
||||
|
|
@ -323,7 +323,7 @@ the rationale. The type is `acknowledged`; it becomes `implemented` with T06.
|
|||
```task
|
||||
id: NK-WP-0048-T06
|
||||
status: wait
|
||||
depends_on: [NK-WP-0048-T05, NK-WP-0048-T08, NK-WP-0048-T09, NK-WP-0048-T12, NK-WP-0048-T13, NK-WP-0048-T14, NK-WP-0048-T15, NK-WP-0048-T16, MASON-WP-0010-T03, WARDEN-WP-0044-T03]
|
||||
depends_on: [NK-WP-0048-T05, NK-WP-0048-T08, NK-WP-0048-T09, NK-WP-0048-T12, NK-WP-0048-T13, NK-WP-0048-T14, NK-WP-0048-T15, NK-WP-0048-T16, NK-WP-0048-T17, NK-WP-0048-T18, MASON-WP-0010-T03, WARDEN-WP-0044-T03]
|
||||
blocking_reason: "Type1.2 architecture has a confirmed source-only founder acknowledgment; canonical1.1 remains unchanged/default and the1.2 reference case stays proposed. Needs explicit version selection/reference-source integration without normal admission bypass, closed owner adapters plus global/native receipt verifier (WARDEN-WP-0044-T03), independently verified six-object structural materialization and CCR42 claims/created-only provenance, exact broker/case/source reconciliation, then separately authorized native mint/delivery and attended registry/consumer verification. Source acknowledgment, a bundle or local tests do not prove implemented/materialized/live status."
|
||||
priority: high
|
||||
state_hub_task_id: "d9b26bcf-a7c6-59a2-92a0-f913d76a203c"
|
||||
|
|
@ -734,10 +734,11 @@ state_hub_task_id: "200bf500-5084-5ae7-be26-3033fe1f296e"
|
|||
```
|
||||
|
||||
Owner: NetKingdom for descriptor/type source and exact checker artifact; Warden
|
||||
independently owns global provenance/admission. Next action: identify the exact
|
||||
reviewed checker executable artifact and native owner evidence/session callback
|
||||
contracts, then assemble the complete step descriptor set and a proposed explicit
|
||||
type version selection. T13's retained descriptor pins a synthetic checker only.
|
||||
independently owns global provenance/admission. Next action: obtain review of the
|
||||
exact checker source/artifact proposed by T17 and identify native owner evidence/
|
||||
session callback contracts, then assemble the complete step descriptor set and
|
||||
a proposed explicit type version selection. T13's historical descriptor retains
|
||||
its synthetic checker; T17 supplies an artifact-bound proposal, not admission.
|
||||
Completion requires separate owner source review of exact machine descriptors,
|
||||
artifact/source/config pins, normal type/version admission and independent
|
||||
evidence-verification boundaries. Warden d97652a refreshes producer validator
|
||||
|
|
@ -746,3 +747,70 @@ machine descriptor into an acknowledged type is a separately reviewed source
|
|||
change. Platform owns structural/mint/broker/delivery evidence; Apps owns actual
|
||||
consumer login/group enforcement. Neither their assent nor native acceptance is
|
||||
supplied by this task.
|
||||
|
||||
## T17 — Build and exercise the exact offline config-checker artifact
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T17
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Completed 2026-10-16, isolated artifact/source fixture proof only. Built the
|
||||
existing `key-cape/src/cmd/keycape` command from published clean source revision
|
||||
`3c71226a1a7b8a2bdb710e9c497e1a1f7f8a3987`, source tree
|
||||
`f0010b9cab17dbc3a787628a29657d98b900320f`, with cached Go 1.23.0,
|
||||
CGO disabled, Linux/amd64 v1, trimmed paths, disabled VCS stamping and offline
|
||||
read-only module selection. The full retained closure pins 108 source files,
|
||||
9876 toolchain files and ten used module source directories. Three isolated
|
||||
build locations produced identical 13633409-byte artifacts:
|
||||
`sha256:be37738fe1c08259fb4f9ca0daf0f9301bfffc237e5bb38435525dfbf11ccff5`.
|
||||
|
||||
Eight disposable checks use the actual executable and maintained helper/kernel,
|
||||
with complete synthetic configs and a minimal environment: add/created-only
|
||||
removal, normal pinned producer admission, rollback, lost-readback uncertainty,
|
||||
stale revisions, substituted checker refusal, invalid startup config and missing
|
||||
secret-env refusal. No checker stub or producer-pin override remains. The
|
||||
artifact-bound descriptor proposal is
|
||||
`sha256:76b1153d188062ece53fcd5e8d35290fdbfd02a69dd79d4b001fc42781afcdc3`.
|
||||
Evidence: Custodian
|
||||
`docs/changes/netkingdom-target-2026-10-16/browser-checker-artifact-next/`.
|
||||
The first two build attempts succeeded but their closure collection failed;
|
||||
both failures are retained, as is refusal of the older incomplete synthetic
|
||||
fixture. No production config, credentials or cluster mutation was used.
|
||||
|
||||
This extracts completed build/fixture scope from T16 without claiming KeyCape
|
||||
owner endorsement, native checker selection/storage custody, acknowledged type
|
||||
integration, native evidence/session callbacks or attended browser acceptance.
|
||||
T16 retains exact owner review and composition/admission scope. The attended
|
||||
registration procedure remains unexercised.
|
||||
|
||||
## T18 — Make checker input and executable selection deterministic
|
||||
|
||||
```task
|
||||
id: NK-WP-0048-T18
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Completed 2026-10-16, isolated source correction and real-artifact fixture proof
|
||||
only; independent integration/publication remain separately recorded. KeyCape
|
||||
source review identified non-secret `KEYCAPE_ACCOUNT_PORTAL_URL` and
|
||||
`KEYCAPE_BROWSER_LOGOUT_URL` overrides in config.Load. The original helper
|
||||
inherited ambient environment, allowing valid supplied configuration to be
|
||||
rejected or invalid supplied URL configuration to be admitted. A bare relative
|
||||
checker filename could also be replaced by PATH lookup after the adapter had
|
||||
hashed the selected local file. All three counterexamples are retained against
|
||||
the unchanged predecessor.
|
||||
|
||||
The existing helper now resolves the selected checker file to an absolute path
|
||||
and passes an explicit empty subprocess environment. Three opt-in real-checker
|
||||
regressions verify both URL-verdict directions and relative-file selection under
|
||||
a non-checker PATH decoy. All 39 affected checks pass with the exact supplied
|
||||
artifact, as do 11 real-artifact helper/kernel scenarios. Source evidence:
|
||||
Custodian `docs/changes/netkingdom-target-2026-10-16/browser-checker-environment-r2/`.
|
||||
Historical descriptors remain retained; the helper correction changes successor
|
||||
source-composition pins and requires their separate review/admission. An absolute
|
||||
path is not immutable custody and does not eliminate file replacement races;
|
||||
T16 retains native executable storage/custody and callback/type admission.
|
||||
No production configuration, credentials or cluster mutation was used.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue