Verify railiance01 identity dependencies
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-07-28 12:59:12 +02:00
parent d674d7f33a
commit 43045cbaf5
4 changed files with 170 additions and 7 deletions

View file

@ -44,7 +44,7 @@
| task | NK-WP-0022-T01 | progress | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T01 | progress | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
| task | NK-WP-0022-T02 | done | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T02 | done | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
| task | NK-WP-0022-T03 | done | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T03 | done | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
| task | NK-WP-0022-T04 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T04 | done | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
| task | NK-WP-0022-T05 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T05 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
| task | NK-WP-0022-T06 | progress | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T06 | progress | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |
| task | NK-WP-0022-T07 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md | | task | NK-WP-0022-T07 | wait | — | workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md |

View file

@ -165,11 +165,30 @@ logs were removed. CoulombCore identity writers remain scaled to zero to
prevent divergence while the railiance01 direct-resolution conformance gates prevent divergence while the railiance01 direct-resolution conformance gates
run; no PVC, Secret, database, or workload declaration was deleted. run; no PVC, Secret, database, or workload declaration was deleted.
## Runtime dependency reconciliation
`sso-mfa/k8s/verify-identity-cutover-dependencies.sh` now provides the
repeatable T04 negative search. It decodes Kubernetes Secret values only in
process memory and reports resource/key locators rather than values.
The live railiance01 run passed all gates:
- no Secret, ConfigMap, Deployment, or StatefulSet in `sso`, `mfa`,
`user-engine`, or `databases` references CoulombCore, its IP, or the public
LLDAP/privacyIDEA endpoints;
- KeyCape resolves LLDAP, Authelia, and privacyIDEA through cluster-local
service names and retains both user-engine and rapp-qonto client declarations;
- privacyIDEA's migrated LLDAP resolver is cluster-local;
- the KeyCape signing-key fingerprint matches CoulombCore;
- LLDAP, Authelia, KeyCape, privacyIDEA, and user-engine deployments are Ready.
TLS-preserving direct resolution to `92.205.62.239` returned HTTP 200 with
successful certificate verification for `auth`, `login`, `lldap`, `pink`,
and `pink-account` under `coulomb.social`.
## Required next evidence ## Required next evidence
1. Reconcile cluster-local configuration and prove that railiance01 has no 1. Exercise platform-root and Binky login/MFA using TLS-preserving direct
runtime dependency on CoulombCore.
2. Exercise platform-root and Binky login/MFA using TLS-preserving direct
resolution to railiance01. resolution to railiance01.
3. Verify KeyCape service-client flows and negative authorization probes. 2. Verify KeyCape service-client flows and negative authorization probes.
4. Move LLDAP and privacyIDEA DNS only after those gates pass. 3. Move LLDAP and privacyIDEA DNS only after those gates pass.

View file

@ -0,0 +1,135 @@
#!/usr/bin/env bash
# Verify that the active identity stack has no runtime dependency on the
# retired/source host. Secret values are decoded only in process memory and
# never printed; failures report resource and key locators only.
set -euo pipefail
KUBECTL="${KUBECTL:-kubectl}"
SOURCE_HOST_MARKER="${SOURCE_HOST_MARKER:-coulombcore}"
SOURCE_IP="${SOURCE_IP:-92.205.130.254}"
NAMESPACES="${NAMESPACES:-sso mfa user-engine databases}"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
for namespace in $NAMESPACES; do
for kind in configmap secret deployment statefulset; do
"$KUBECTL" -n "$namespace" get "$kind" -o json \
>"$tmp/${namespace}-${kind}.json"
done
done
python3 - "$tmp" "$SOURCE_HOST_MARKER" "$SOURCE_IP" <<'PY'
import base64
import json
import pathlib
import sys
root = pathlib.Path(sys.argv[1])
patterns = {
"source-host": sys.argv[2].lower(),
"source-ip": sys.argv[3].lower(),
"public-lldap": "lldap.coulomb.social",
"public-privacyidea": "pink.coulomb.social",
"public-privacyidea-account": "pink-account.coulomb.social",
}
failures = []
for path in sorted(root.glob("*.json")):
namespace, kind = path.stem.rsplit("-", 1)
for item in json.loads(path.read_text()).get("items", []):
name = item["metadata"]["name"]
if kind in {"configmap", "secret"}:
for key, raw in (item.get("data") or {}).items():
try:
value = (
base64.b64decode(raw).decode("utf-8", "replace")
if kind == "secret"
else raw
)
except Exception:
continue
lowered = value.lower()
hits = [label for label, needle in patterns.items() if needle in lowered]
if hits:
failures.append(
f"{kind}/{namespace}/{name}:{key} matches={','.join(hits)}"
)
else:
lowered = json.dumps(item.get("spec", {}), sort_keys=True).lower()
hits = [label for label, needle in patterns.items() if needle in lowered]
if hits:
failures.append(
f"{kind}/{namespace}/{name} matches={','.join(hits)}"
)
if failures:
print("stale_dependencies=found")
for failure in failures:
print(failure)
raise SystemExit(1)
print("stale_dependencies=absent")
PY
keycape_config="$(
"$KUBECTL" -n sso get secret keycape-config \
-o jsonpath='{.data.config\.yaml}' | base64 -d
)"
for expected in \
lldap.sso.svc.cluster.local \
authelia.sso.svc.cluster.local \
privacyidea.mfa.svc.cluster.local \
user-engine \
rapp-qonto
do
if [[ "$keycape_config" != *"$expected"* ]]; then
echo "keycape_expected_dependency_missing=$expected" >&2
exit 1
fi
done
unset keycape_config
echo "keycape_dependencies=cluster-local-and-complete"
pg_pod="$(
"$KUBECTL" -n databases get pod \
-l 'cnpg.io/cluster=net-kingdom-pg,role=primary' \
-o jsonpath='{.items[0].metadata.name}'
)"
resolver_class="$(
"$KUBECTL" -n databases exec "$pg_pod" -- \
psql -X -A -t -U postgres -d privacyidea_db -c \
"select case
when lower(\"Value\") like '%lldap.sso.svc.cluster.local%'
then 'cluster-local'
else 'other'
end
from resolverconfig
where \"Key\"='LDAPURI';" 2>/dev/null
)"
if [[ "$resolver_class" != "cluster-local" ]]; then
echo "privacyidea_lldap_resolver=$resolver_class" >&2
exit 1
fi
echo "privacyidea_lldap_resolver=cluster-local"
for target in \
sso/lldap \
sso/authelia \
sso/keycape \
mfa/privacyidea \
user-engine/user-engine
do
namespace="${target%/*}"
name="${target#*/}"
ready="$(
"$KUBECTL" -n "$namespace" get deployment "$name" \
-o jsonpath='{.status.readyReplicas}'
)"
if [[ "${ready:-0}" -lt 1 ]]; then
echo "deployment_not_ready=$target" >&2
exit 1
fi
done
echo "identity_deployments=ready"
echo "identity_cutover_dependencies=PASS"

View file

@ -141,7 +141,7 @@ CoulombCore writers remain frozen against divergence.
```task ```task
id: NK-WP-0022-T04 id: NK-WP-0022-T04
status: wait status: done
priority: high priority: high
state_hub_task_id: "33591ee3-586e-4ac6-82e6-0ab4642cea5e" state_hub_task_id: "33591ee3-586e-4ac6-82e6-0ab4642cea5e"
``` ```
@ -155,6 +155,15 @@ points back to CoulombCore.
Done when an automated dependency graph and negative search prove there are Done when an automated dependency graph and negative search prove there are
no hidden CoulombCore runtime dependencies. no hidden CoulombCore runtime dependencies.
2026-07-28: added
`sso-mfa/k8s/verify-identity-cutover-dependencies.sh`. Its live railiance01
run found no CoulombCore IP/host or public cross-cluster endpoint in decoded
identity Secrets, ConfigMaps, Deployments, or StatefulSets. It verified
cluster-local KeyCape and privacyIDEA dependencies, retained user-engine and
rapp-qonto clients, and Ready deployments. KeyCape signing fingerprints
match. TLS-preserving direct resolution returned HTTP 200 with valid
certificates for `auth`, `login`, `lldap`, `pink`, and `pink-account`.
## T05 - Run full pre-cutover identity conformance ## T05 - Run full pre-cutover identity conformance
```task ```task