Adopt the agent environment orientation for KeyCape's live objects.
Write Secrets with kubectl replace in the rotation script, since apply copies the data into the last-applied annotation. Record in operations.md the live-change rules that apply here and the open finding: four live Secrets carry that annotation, and removing it waits for the founder's go-ahead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 352750@bnt-lap001 Assistant-Session: de41ef1c-2113-4dd2-9b92-f318ffa7f98b
This commit is contained in:
parent
012e695947
commit
51e541c9a1
3 changed files with 50 additions and 4 deletions
|
|
@ -3,6 +3,10 @@
|
|||
Dev Hub (State Hub API): http://127.0.0.1:8000
|
||||
MCP server name in `~/.claude.json`: `dev-hub`
|
||||
|
||||
**Before production, credential or GitOps work** read
|
||||
`~/the-custodian/docs/agent-environment-orientation.md`; KeyCape specifics are
|
||||
in `docs/operations.md`, "Before any live change".
|
||||
|
||||
**Step 1 — Orient**
|
||||
|
||||
Read the offline-safe brief first — it works without a live hub connection:
|
||||
|
|
|
|||
|
|
@ -125,12 +125,42 @@ curl -s -H "Host: auth.coulomb.social" \
|
|||
| jq -r .issuer
|
||||
```
|
||||
|
||||
## Before any live change
|
||||
|
||||
The estate-wide rules are in
|
||||
`the-custodian/docs/agent-environment-orientation.md` (revision 2026-09-21);
|
||||
read it first. The parts that apply to KeyCape's objects in `sso` and `mfa`:
|
||||
|
||||
- The founder's go-ahead comes first, recorded as
|
||||
`ADMINISTER @ realm:kubernetes/railiance01`, `activation=APPROVED`. Run changes
|
||||
as `ssh railiance01 '…'`. A harness block is a stop signal, not something to
|
||||
route around.
|
||||
- Check CPU headroom before a restart or rollout
|
||||
(`kubectl describe node | grep -A4 "Allocated resources"`). A rolling update
|
||||
starts the new pod before stopping the old one.
|
||||
- Diff first: client-side `kubectl diff`, then `--dry-run=server`.
|
||||
- **Never `kubectl apply` a Secret, and never read one's metadata.** `apply`
|
||||
copies the whole Secret into the `last-applied-configuration` annotation, so
|
||||
even a metadata read prints the signing key and client secrets. Write Secrets
|
||||
with `kubectl replace`. To test for the annotation without printing it:
|
||||
`kubectl get secret <n> -n sso -o go-template='{{ if index .metadata.annotations "kubectl.kubernetes.io/last-applied-configuration" }}HAS-ANNOTATION{{ else }}clean{{ end }}'`.
|
||||
|
||||
**Open finding, 2026-09-23:** `sso/keycape-config`, `sso/authelia-secrets`,
|
||||
`sso/lldap-secrets` and `mfa/privacyidea-config` all carry that annotation. The
|
||||
earlier rotation script wrote them with `apply`; it now uses `replace`. Anyone
|
||||
who can `get` these Secrets could read the data anyway, so this is not a new
|
||||
reader. What it breaks is the assumption that a metadata read is safe. The fix
|
||||
is a live change and waits for the founder's go-ahead:
|
||||
`kubectl annotate secret <n> -n <ns> kubectl.kubernetes.io/last-applied-configuration-`
|
||||
for each of the four. It prints no value and leaves `.data` untouched, so pods
|
||||
need no restart. Re-check with the template above afterwards.
|
||||
|
||||
## Unreleased fail-closed startup changes (read before the next rollout)
|
||||
|
||||
The deployed image at the time of writing is
|
||||
`sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611`, built
|
||||
from `dcebd46`. Two changes on `main` postdate it, both affect startup or
|
||||
issuance, and **both fail closed**, so they land together on the next rollout and
|
||||
from `dcebd46`. The changes below on `main` postdate it, all affect startup or
|
||||
issuance, and **all fail closed**, so they land together on the next rollout and
|
||||
a mistake in either presents as a refusal rather than as a warning.
|
||||
|
||||
**1. Browser clients reject service-identity fields (`74b35b6`, KEY-WP-0028).**
|
||||
|
|
@ -155,7 +185,15 @@ grant today, so nothing changes on rollout; the refusal only becomes reachable
|
|||
once the approver client is registered. See
|
||||
[the tenant contract](tenant-claim-contract.md).
|
||||
|
||||
Neither has been exercised against a running issuer. The honest proof for both is
|
||||
**3. KeyCape enforces login freshness itself (`11ce29a`, KEY-WP-0033).**
|
||||
`prompt=login` is no longer forwarded to Authelia, because 4.38 refuses it for
|
||||
every real login. `prompt=login` and `max_age=0` go upstream as `max_age=10`,
|
||||
and the callback refuses any upstream `auth_time` that misses the requirement,
|
||||
or is absent (`stale_upstream_authentication`). This changes nothing for clients
|
||||
that do not ask for freshness. The proof is a completed fresh-login journey,
|
||||
not a redirect check.
|
||||
|
||||
None of these has been exercised against a running issuer. The honest proof for both is
|
||||
a live boot with the new binary, which belongs to the attended rollout window and
|
||||
not to a session running against production on its own.
|
||||
|
||||
|
|
|
|||
|
|
@ -283,8 +283,12 @@ sys.stdout.write(updated)
|
|||
kubectl create configmap authelia-config -n sso --from-file=configuration.yml="$work_dir/authelia-configuration.updated.yml" --dry-run=client -o yaml |
|
||||
kubectl apply -f - >/dev/null
|
||||
|
||||
# replace, not apply: apply copies the full Secret data into the
|
||||
# last-applied-configuration annotation, where any metadata read prints it.
|
||||
# replace writes only the manifest, which also drops an annotation left by an
|
||||
# earlier apply.
|
||||
kubectl create secret generic keycape-config -n sso --from-file=config.yaml="$work_dir/config.yaml" --from-file=key.pem="$work_dir/key.pem" --dry-run=client -o yaml |
|
||||
kubectl apply -f - >/dev/null
|
||||
kubectl replace -f - >/dev/null
|
||||
|
||||
kubectl rollout restart deployment/authelia deployment/keycape -n sso >/dev/null
|
||||
kubectl rollout status deployment/authelia -n sso --timeout=180s
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue