87 lines
4.1 KiB
Python
87 lines
4.1 KiB
Python
|
|
"""Rows C4 and C5: the custody names agree across net-kingdom, railiance-platform and audit-core (NK-WP-0058-T02).
|
||
|
|
|
||
|
|
C4, KeyCape client secret: railiance-platform's ESO template and rendered manifest, CCR-2026-0061's KV path, and
|
||
|
|
net-kingdom's keycape-client.py naming and the KeyCape Deployment's env binding.
|
||
|
|
C5, audit-core sender bearer: CCR-2026-0063's KV path, fields and delivery, the platform's ExternalSecret, and the
|
||
|
|
names audit-core's seeder uses (read as text; the seeder is not imported).
|
||
|
|
The rapp Job's mount of sso/bounded-executor-tokens is private and checked in the rapp's own CI.
|
||
|
|
"""
|
||
|
|
import importlib.util
|
||
|
|
import re
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
import yaml
|
||
|
|
|
||
|
|
REPO = Path(__file__).resolve().parents[3]
|
||
|
|
PLATFORM = REPO.parent / 'railiance-platform'
|
||
|
|
AUDIT_CORE = REPO.parent / 'audit-core'
|
||
|
|
ESO = PLATFORM / 'manifests/nk-bind-executor-eso.yaml'
|
||
|
|
CCRS = PLATFORM / 'credential-change-requests'
|
||
|
|
|
||
|
|
|
||
|
|
def need(*paths):
|
||
|
|
for path in paths:
|
||
|
|
if not path.exists():
|
||
|
|
pytest.skip(f'owner checkout missing: {path.parent.name}/{path.name}')
|
||
|
|
|
||
|
|
|
||
|
|
def ccr(prefix):
|
||
|
|
return yaml.safe_load(next(CCRS.glob(prefix + '-*.yaml')).read_text())
|
||
|
|
|
||
|
|
|
||
|
|
def external_secrets():
|
||
|
|
docs = [d for d in yaml.safe_load_all(ESO.read_text()) if d]
|
||
|
|
stores = {d['metadata']['name']: d for d in docs if d['kind'] == 'ClusterSecretStore'}
|
||
|
|
return {d['spec']['target']['name']: (d, stores[d['spec']['secretStoreRef']['name']])
|
||
|
|
for d in docs if d['kind'] == 'ExternalSecret'}
|
||
|
|
|
||
|
|
|
||
|
|
def kv_path(store, remote_key):
|
||
|
|
return store['spec']['provider']['vault']['path'].strip('/') + '/' + remote_key
|
||
|
|
|
||
|
|
|
||
|
|
def keycape_client():
|
||
|
|
spec = importlib.util.spec_from_file_location('kc_client_names', REPO / 'sso-mfa/k8s/keycape/keycape-client.py')
|
||
|
|
module = importlib.util.module_from_spec(spec)
|
||
|
|
spec.loader.exec_module(module)
|
||
|
|
return module
|
||
|
|
|
||
|
|
|
||
|
|
def test_c4_keycape_client_secret_names():
|
||
|
|
need(ESO, PLATFORM / 'manifests/templates/keycape-issuer-eso.yaml')
|
||
|
|
kc = keycape_client()
|
||
|
|
case = yaml.safe_load((REPO / 'security-cases/nk-bind-executor-approval.yaml').read_text())['spec']
|
||
|
|
cid = case['parameters']['client_id']
|
||
|
|
secret_name, env = kc.env_secret_name(cid), kc.env_name(cid)
|
||
|
|
template = (PLATFORM / 'manifests/templates/keycape-issuer-eso.yaml').read_text()
|
||
|
|
assert 'name: keycape-{client_id}-client' in template, 'template naming convention changed'
|
||
|
|
assert kc.env_secret_name('{client_id}') == 'keycape-{client_id}-client'
|
||
|
|
es, store = external_secrets()[secret_name]
|
||
|
|
(item,) = es['spec']['data']
|
||
|
|
custody = ccr('CCR-2026-0061')['openbao']
|
||
|
|
assert item['secretKey'] == 'client-secret'
|
||
|
|
assert kv_path(store, item['remoteRef']['key']) == custody['kv_path'] == f'platform/workloads/keycape/{cid}'
|
||
|
|
assert [item['remoteRef']['property']] == custody['fields'] == ['CLIENT_SECRET']
|
||
|
|
deployment = next(d for d in yaml.safe_load_all((REPO / 'sso-mfa/k8s/keycape/deployment.yaml').read_text())
|
||
|
|
if d and d['kind'] == 'Deployment' and d['metadata']['name'] == 'keycape')
|
||
|
|
bound = {e['name']: e.get('valueFrom', {}).get('secretKeyRef') for c in deployment['spec']['template']['spec']
|
||
|
|
['containers'] for e in c.get('env', [])}
|
||
|
|
assert bound.get(env) == {'name': secret_name, 'key': 'client-secret'}, 'KeyCape env binding differs'
|
||
|
|
|
||
|
|
|
||
|
|
def test_c5_audit_sender_custody_names():
|
||
|
|
seeder = AUDIT_CORE / 'scripts/seed-nk-bounded-executor-sender.py'
|
||
|
|
need(ESO, seeder)
|
||
|
|
constants = dict(re.findall(r'^([A-Z_]+) = "([^"]*)"', seeder.read_text(), re.M))
|
||
|
|
custody = ccr('CCR-2026-0063')
|
||
|
|
es, store = external_secrets()[constants['SSO_SECRET']]
|
||
|
|
(item,) = es['spec']['data']
|
||
|
|
assert es['metadata']['namespace'] == custody['delivery']['namespace'] == 'sso'
|
||
|
|
assert custody['openbao']['kv_path'] == constants['CUSTODY_KV'] == kv_path(store, item['remoteRef']['key'])
|
||
|
|
assert item['remoteRef']['property'] in custody['openbao']['fields'] == ['AUDIT_TOKEN', 'CUSTODY_REQUEST']
|
||
|
|
assert item['secretKey'] == constants['SSO_KEY'] == 'audit-core'
|
||
|
|
target = custody['delivery']['target']
|
||
|
|
assert f"sso/{constants['SSO_SECRET']}" in target and constants['SSO_KEY'] in target
|
||
|
|
assert constants['CCR_ID'] == custody['id']
|