Move portal workloads to registry digests
This commit is contained in:
parent
52b57c99f7
commit
f854969a01
6 changed files with 42 additions and 17 deletions
|
|
@ -1,24 +1,26 @@
|
||||||
{
|
{
|
||||||
"captured_at": "2026-07-29T21:56:00Z",
|
"captured_at": "2026-07-29T22:16:00Z",
|
||||||
"checks": {
|
"checks": {
|
||||||
"backup_archive_catalog_valid": true,
|
"backup_archive_catalog_valid": true,
|
||||||
"backup_checksum_valid": true,
|
"backup_checksum_valid": true,
|
||||||
"backup_schedule_present": true,
|
"backup_schedule_present": true,
|
||||||
"database_ready": true,
|
"database_ready": true,
|
||||||
|
"identity_provisioner_registry_public_read": true,
|
||||||
"metrics_authorized": true,
|
"metrics_authorized": true,
|
||||||
"metrics_unauthorized_denied": true,
|
"metrics_unauthorized_denied": true,
|
||||||
"restore_drill_complete": true,
|
"restore_drill_complete": true,
|
||||||
"restore_migration_rows": 1,
|
"restore_migration_rows": 1,
|
||||||
"restore_public_tables": 4,
|
"restore_public_tables": 4,
|
||||||
"rollback_exercised": true,
|
"rollback_exercised": true,
|
||||||
"rollforward_restored": true
|
"rollforward_restored": true,
|
||||||
|
"user_engine_offsite_age_upload": true,
|
||||||
|
"user_engine_registry_public_read": true
|
||||||
},
|
},
|
||||||
"declared_image": "user-engine:portal-2bcda7f",
|
"declared_image": "forgejo.coulomb.social/coulomb/user-engine@sha256:60f4fa1c144c8f7b9e2e74c264e4594e63ac6a0c0f75e5cf536880b8fd99fa28",
|
||||||
"residual_risks": [
|
"identity_provisioner_image": "forgejo.coulomb.social/coulomb/identity-provisioner@sha256:ecd9ba44bb83a4809fb47e0ef016e3f71f38a87f1adbdbf0a102ac24c12f6df8",
|
||||||
"Backup PVC uses the reef's single local node and is not an independent disaster-recovery copy.",
|
"offsite_artifact": "user-engine-pg-user_engine-20260729T220653Z.dump.age",
|
||||||
"The directly imported image still needs publication through the approved registry lane."
|
"residual_risks": [],
|
||||||
],
|
"rollback_image": "forgejo.coulomb.social/coulomb/user-engine@sha256:d25037e61c0c71dd9fbf89f653797932061b0be1fc5b4b23223821e5c2e3d6d0",
|
||||||
"rollback_image": "user-engine:portal-746bf21",
|
|
||||||
"schema_version": "user-engine-operability-evidence/v1",
|
"schema_version": "user-engine-operability-evidence/v1",
|
||||||
"secret_values_observed": false
|
"secret_values_observed": false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ spec:
|
||||||
seccompProfile: {type: RuntimeDefault}
|
seccompProfile: {type: RuntimeDefault}
|
||||||
containers:
|
containers:
|
||||||
- name: provisioner
|
- name: provisioner
|
||||||
image: identity-provisioner:12cdef5
|
image: forgejo.coulomb.social/coulomb/identity-provisioner@sha256:ecd9ba44bb83a4809fb47e0ef016e3f71f38a87f1adbdbf0a102ac24c12f6df8
|
||||||
imagePullPolicy: Never
|
imagePullPolicy: IfNotPresent
|
||||||
ports: [{name: http, containerPort: 8080}]
|
ports: [{name: http, containerPort: 8080}]
|
||||||
env:
|
env:
|
||||||
- {name: LLDAP_URL, value: "http://lldap.sso.svc.cluster.local:17170"}
|
- {name: LLDAP_URL, value: "http://lldap.sso.svc.cluster.local:17170"}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,11 @@ no public Ingress until the KeyCape authorization-code/PKCE edge and
|
||||||
must remain impossible because the application accepts identity only from a
|
must remain impossible because the application accepts identity only from a
|
||||||
trusted edge marker plus verified claims.
|
trusted edge marker plus verified claims.
|
||||||
|
|
||||||
For the current pre-production bootstrap the image is imported directly into
|
The portal image is published through the activity-core workload-scoped
|
||||||
k3s and uses `imagePullPolicy: Never`. Replace it with the immutable Forgejo
|
Forgejo package credential and deployed from
|
||||||
OCI digest after the OpenBao package-publisher lane is available.
|
`forgejo.coulomb.social/coulomb/user-engine` by immutable digest. The public
|
||||||
|
package read was verified without an image pull Secret; publishing still uses
|
||||||
|
the ExternalSecret-backed credential and temporary client state.
|
||||||
|
|
||||||
The CloudNativePG operator creates `user-engine-pg-app`, including its `uri`
|
The CloudNativePG operator creates `user-engine-pg-app`, including its `uri`
|
||||||
field. `user-engine-runtime` contains only the generated edge marker and must
|
field. `user-engine-runtime` contains only the generated edge marker and must
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ spec:
|
||||||
seccompProfile: {type: RuntimeDefault}
|
seccompProfile: {type: RuntimeDefault}
|
||||||
containers:
|
containers:
|
||||||
- name: portal
|
- name: portal
|
||||||
image: user-engine:portal-2bcda7f
|
image: forgejo.coulomb.social/coulomb/user-engine@sha256:60f4fa1c144c8f7b9e2e74c264e4594e63ac6a0c0f75e5cf536880b8fd99fa28
|
||||||
imagePullPolicy: Never
|
imagePullPolicy: IfNotPresent
|
||||||
ports: [{name: http, containerPort: 8080}]
|
ports: [{name: http, containerPort: 8080}]
|
||||||
env:
|
env:
|
||||||
- name: USER_ENGINE_DATABASE_URL
|
- name: USER_ENGINE_DATABASE_URL
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ set -euo pipefail
|
||||||
namespace=user-engine
|
namespace=user-engine
|
||||||
deployment=user-engine
|
deployment=user-engine
|
||||||
manifest="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/runtime.yaml"
|
manifest="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/runtime.yaml"
|
||||||
|
rollback_target="${USER_ENGINE_ROLLBACK_IMAGE:-forgejo.coulomb.social/coulomb/user-engine@sha256:d25037e61c0c71dd9fbf89f653797932061b0be1fc5b4b23223821e5c2e3d6d0}"
|
||||||
exercise_rollback=false
|
exercise_rollback=false
|
||||||
if [[ "${1:-}" == "--exercise-rollback" ]]; then
|
if [[ "${1:-}" == "--exercise-rollback" ]]; then
|
||||||
exercise_rollback=true
|
exercise_rollback=true
|
||||||
|
|
@ -47,12 +48,13 @@ print("%s %s %s" % (denied, response.status, int("user_engine_ready 1" in body))
|
||||||
rollback_image=""
|
rollback_image=""
|
||||||
rollback_restored=true
|
rollback_restored=true
|
||||||
if $exercise_rollback; then
|
if $exercise_rollback; then
|
||||||
kubectl -n "$namespace" rollout undo deployment/"$deployment" >/dev/null
|
kubectl -n "$namespace" set image deployment/"$deployment" \
|
||||||
|
"portal=${rollback_target}" >/dev/null
|
||||||
kubectl -n "$namespace" rollout status deployment/"$deployment" \
|
kubectl -n "$namespace" rollout status deployment/"$deployment" \
|
||||||
--timeout=180s >/dev/null
|
--timeout=180s >/dev/null
|
||||||
rollback_image="$(kubectl -n "$namespace" get deployment "$deployment" \
|
rollback_image="$(kubectl -n "$namespace" get deployment "$deployment" \
|
||||||
-o jsonpath='{.spec.template.spec.containers[0].image}')"
|
-o jsonpath='{.spec.template.spec.containers[0].image}')"
|
||||||
[[ "$rollback_image" != "$current_image" ]]
|
[[ "$rollback_image" == "$rollback_target" ]]
|
||||||
kubectl apply -f "$manifest" >/dev/null
|
kubectl apply -f "$manifest" >/dev/null
|
||||||
kubectl -n "$namespace" rollout status deployment/"$deployment" \
|
kubectl -n "$namespace" rollout status deployment/"$deployment" \
|
||||||
--timeout=180s >/dev/null
|
--timeout=180s >/dev/null
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,25 @@ The remaining production gaps are registry publication and an independently
|
||||||
custodied/off-node backup copy; the current PVC shares reef-railiance's single
|
custodied/off-node backup copy; the current PVC shares reef-railiance's single
|
||||||
failure domain, so T05 remains in progress.
|
failure domain, so T05 remains in progress.
|
||||||
|
|
||||||
|
2026-07-30 follow-up: both former gaps are implemented. The activity-core
|
||||||
|
ExternalSecret boundary published the portal and provisioner images to
|
||||||
|
`forgejo.coulomb.social` without exposing the package credential. Anonymous
|
||||||
|
digest inspection passed, and both live Deployments now pull immutable public
|
||||||
|
digests. The prior verified portal image is also published by digest;
|
||||||
|
rollback/roll-forward passed without node-local image reliance.
|
||||||
|
|
||||||
|
The established Option A activity-core lane produced and uploaded
|
||||||
|
`user-engine-pg-user_engine-20260729T220653Z.dump.age` to independent
|
||||||
|
Nextcloud custody. The plaintext dump was removed immediately and only
|
||||||
|
non-secret sizes and the artifact name were recorded. The local isolated
|
||||||
|
restore drill already proves the same logical dump/restore path.
|
||||||
|
|
||||||
|
The final T05 custody residual is narrower: `user-engine-runtime/proxy-secret`
|
||||||
|
and `identity-provisioner-client/token` remain bootstrap Kubernetes Secrets.
|
||||||
|
They must move to an OpenBao-owned path plus ExternalSecret and a rotation
|
||||||
|
procedure. Creating that new write/custody lane requires the ops-mason
|
||||||
|
executive approval gate; registry and backup work do not remain open.
|
||||||
|
|
||||||
## T06 - Prove role-scoped administration and failure safety
|
## T06 - Prove role-scoped administration and failure safety
|
||||||
|
|
||||||
```task
|
```task
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue