RKE2 BLOODBAG dev signal-source Redis Secrets¶
이 문서는 tirosh-gitops #257/#263과 PR #258 dest가 internal-push mode에서
기대하는 Secret registry와 additive legacy-live-v1 pair
(bloodbag-dev-legacy-live-redis-v1, bloodbag-dev-legacy-live-policy-v1)를
다룹니다. 값은 Git에 두지 않으며, 유일한 소유자는
sites/tirosh-home/secrets.toml과 기존 infra-tools secret입니다.
아래 기존 five-secret 계약, 예시, rollback은 그대로 유지합니다.
하지 않는 것: Secret apply, cluster 변경, pull-source Secret, CySec material
bootstrap 재사용, SMC/BLOODBAG_DEV_REDIS_PASSWORD 재사용, Cilium KPR/L2.
계약¶
Context tirosh-home/rke2/gpu, namespace bloodbag-dev. Secret type은
Opaque입니다.
| ID | Name | Keys and required environment source |
|---|---|---|
bloodbag-dev-signal-source-redis-tls |
bloodbag-signal-source-redis-tls |
tls.crt ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CERT; tls.key ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_KEY; ca.crt ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CA |
bloodbag-dev-signal-source-redis-vital-file-streamer |
bloodbag-signal-source-redis-vital-file-streamer |
password ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_VITAL_FILE_STREAMER_PASSWORD |
bloodbag-dev-signal-source-redis-external-producer |
bloodbag-signal-source-redis-external-producer |
password ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_EXTERNAL_PRODUCER_PASSWORD |
bloodbag-dev-signal-source-redis-signal-relay |
bloodbag-signal-source-redis-signal-relay |
password ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_SIGNAL_RELAY_PASSWORD |
bloodbag-dev-signal-source-redis-health |
bloodbag-signal-source-redis-health |
password ← BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_HEALTH_PASSWORD |
네 ACL password 입력은 서로 달라야 합니다. GitOps runtime이 users.acl을 만들 때
이 불변 조건을 강제합니다. TLS 서버 인증서 SAN은 정확히 다음 두 이름입니다.
source.dev.bloodbag.internal.tirosh.ai
bloodbag-signal-source-redis.bloodbag-dev.svc
PEM은 기존 env stringData 경로로만 넣습니다. 별도 secret tool이나 file source를
추가하지 않습니다. --from-literal과 --show-values는 사용하지 않습니다.
describe, redacted render, dummy dry-run, apply¶
로컬 미커밋 .env(mode 0600) 또는 export VAR="$(cat file)"로 값을 주입합니다.
값 자체는 출력하지 않습니다.
uv run --package infra-tools infra-tools secret describe \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-tls
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CERT=dummy \
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_KEY=dummy \
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CA=dummy \
uv run --package infra-tools infra-tools secret render \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-tls
make kubernetes/secret/plan SITE=tirosh-home \
KUBERNETES_SECRET=bloodbag-dev-signal-source-redis-tls
describe와 plan/render는 redacted입니다. apply --dry-run은 kubectl이 dummy
값을 보여 주므로 실제 PEM/password를 넣지 않습니다. 각 password ID도 같은 순서로
확인한 뒤 ID마다 apply합니다.
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CERT="$(cat "$TLS_DIR/tls.crt")"
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_KEY="$(cat "$TLS_DIR/tls.key")"
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CA="$(cat "$TLS_DIR/ca.crt")"
uv run --package infra-tools infra-tools secret apply \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-tls
unset BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CERT \
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_KEY \
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_TLS_CA
password는 자식 infra-tools 프로세스가 읽도록 먼저 export한 뒤 read로
넣습니다. read -r -s VAR만 하면 변수는 현재 shell에만 남고 apply가
missing environment variable로 실패합니다. 값을 echo하거나 Git에 쓰지 않습니다.
적용 직후 unset합니다.
uv run --package infra-tools infra-tools secret describe \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-vital-file-streamer
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_VITAL_FILE_STREAMER_PASSWORD=dummy \
uv run --package infra-tools infra-tools secret render \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-vital-file-streamer
make kubernetes/secret/plan SITE=tirosh-home \
KUBERNETES_SECRET=bloodbag-dev-signal-source-redis-vital-file-streamer
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_VITAL_FILE_STREAMER_PASSWORD
IFS= read -r -s BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_VITAL_FILE_STREAMER_PASSWORD
uv run --package infra-tools infra-tools secret apply \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-vital-file-streamer
unset BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_VITAL_FILE_STREAMER_PASSWORD
uv run --package infra-tools infra-tools secret describe \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-external-producer
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_EXTERNAL_PRODUCER_PASSWORD=dummy \
uv run --package infra-tools infra-tools secret render \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-external-producer
make kubernetes/secret/plan SITE=tirosh-home \
KUBERNETES_SECRET=bloodbag-dev-signal-source-redis-external-producer
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_EXTERNAL_PRODUCER_PASSWORD
IFS= read -r -s BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_EXTERNAL_PRODUCER_PASSWORD
uv run --package infra-tools infra-tools secret apply \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-external-producer
unset BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_EXTERNAL_PRODUCER_PASSWORD
uv run --package infra-tools infra-tools secret describe \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-signal-relay
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_SIGNAL_RELAY_PASSWORD=dummy \
uv run --package infra-tools infra-tools secret render \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-signal-relay
make kubernetes/secret/plan SITE=tirosh-home \
KUBERNETES_SECRET=bloodbag-dev-signal-source-redis-signal-relay
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_SIGNAL_RELAY_PASSWORD
IFS= read -r -s BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_SIGNAL_RELAY_PASSWORD
uv run --package infra-tools infra-tools secret apply \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-signal-relay
unset BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_SIGNAL_RELAY_PASSWORD
uv run --package infra-tools infra-tools secret describe \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-health
BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_HEALTH_PASSWORD=dummy \
uv run --package infra-tools infra-tools secret render \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-health
make kubernetes/secret/plan SITE=tirosh-home \
KUBERNETES_SECRET=bloodbag-dev-signal-source-redis-health
export BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_HEALTH_PASSWORD
IFS= read -r -s BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_HEALTH_PASSWORD
uv run --package infra-tools infra-tools secret apply \
--site tirosh-home \
--secret bloodbag-dev-signal-source-redis-health
unset BLOODBAG_DEV_SIGNAL_SOURCE_REDIS_HEALTH_PASSWORD
운영자 소유와 rollback¶
사람 운영자(human operator)가 generation, apply, verification, rotation, 그리고
secure handoff를 소유합니다. infra-tools secret apply is direct kubectl apply
and does not snapshot/rollback.
consumer activation 전에는 non-secret metadata만 기록합니다. 이미 있는 Secret을 교체할 때는 Git에 값을 쓰지 말고, secure out-of-Git backup을 두거나 같은 계약을 regenerate할 수 있어야 합니다.
rollback은 previous known-good material을 다시 apply하거나, 일관된 five-secret set을 새로 만들어 apply하는 것입니다. 적용 후 keys, SAN, four distinct passwords를 확인하고, PR #258 consumer activation은 상황에 맞게 keep하거나 revert합니다. deleting these Secrets while consumers run is forbidden.
Bounded legacy-live-v1 appendix¶
This appendix is the bounded operational record for the additive generation-v1 pair only. The five-secret contracts, examples, and rollback assertions above stay in force for those five Secrets. Do not use that old five-secret rollback procedure as a mechanism for this pair.
| ID | Name | Namespace | Context | Type | Keys and required environment source |
|---|---|---|---|---|---|
bloodbag-dev-legacy-live-redis-v1 |
bloodbag-dev-legacy-live-redis-v1 |
bloodbag-dev |
tirosh-home/rke2/gpu |
Opaque |
password ← BLOODBAG_DEV_LEGACY_LIVE_REDIS_V1_PASSWORD; users.acl ← BLOODBAG_DEV_LEGACY_LIVE_REDIS_V1_USERS_ACL |
bloodbag-dev-legacy-live-policy-v1 |
bloodbag-dev-legacy-live-policy-v1 |
bloodbag-dev |
tirosh-home/rke2/gpu |
Opaque |
service-token ← BLOODBAG_DEV_LEGACY_LIVE_POLICY_V1_SERVICE_TOKEN |
Annotation bloodbag.tirosh.ai/credential-generation is v1. Labels are
app.kubernetes.io/managed-by=infra-tools, app.kubernetes.io/part-of=bloodbag,
and tirosh.ai/environment=dev. The registry has no immutable field. The
existing parser and SecretSpec do not implement it, so a TOML immutable flag is
not written.
The human operator, who is the human custodian named later by Root in the
private operational record, generates one high-entropy printable UTF-8 producer
password and a distinct whitespace-free service token of 32..4096 UTF-8 bytes.
Do not reuse SMC, source, default, or runtime credentials. The complete
users.acl environment string contains exactly the preserved default semantics
and the frozen named producer ACL, with no extra users or selectors. The
default nonsecret semantic line may be user default reset on nopass sanitize-payload ~* &* +@all.
The producer hash is derived privately from the exact password bytes. Validate
matching hash, nonempty material, token grammar, and actual ACL syntax
privately, and report only booleans. SecretSpec does not check those semantics.
Hold the three environment variables in an exported environment or a protected
private ENV_FILE: a regular 0600 file in a private 0700 directory, trusted shell
assignments only, excluded from Git, logs, and artifacts. A bare ignored.env
name is not itself an exclusion. Before apply, place the exact password, the
complete ACL, and the token, or exact reproducing inputs, into the human
custodian's secure out-of-Git backup. A temporary copy, an ignored file, a live
Secret, or an etcd snapshot is not a recovery receipt. Retrieve from that backup
into an isolated private process and verify byte-for-byte identity plus
password/ACL agreement, reporting booleans only. A newly regenerated random
token or password is a rotation, not exact restoration.
No custody receipt exists yet. No handoff is established. Public evidence has
no backup values, password hashes, token, or ACL body. Current flags:
material_generated=false, secret_applied=false,
recoverability_verified=false, immutable_verified=false,
operator_handoff=unestablished.
Plans below are redacted future parent steps, not executed evidence. Actual
dry-run is forbidden; only unmistakable dummy env in an isolated test may use
apply --dry-run. Authorized apply is serial and must pass explicit
KUBECTX=tirosh-home/rke2/gpu together with the registry context. Apply offers
no automatic snapshot or rollback, and it is not atomic across the two Secrets.
Unset all three variables after use. Do not print full annotations, Secret
YAML/JSON, manifest stdin, shell tracing, --show-values, or --from-literal.
make kubernetes/secret/plan SITE=tirosh-home ENV_FILE=<protected-absolute-path> KUBERNETES_SECRET=bloodbag-dev-legacy-live-redis-v1
make kubernetes/secret/plan SITE=tirosh-home ENV_FILE=<protected-absolute-path> KUBERNETES_SECRET=bloodbag-dev-legacy-live-policy-v1
make kubernetes/secret/apply SITE=tirosh-home ENV_FILE=<protected-absolute-path> KUBECTX=tirosh-home/rke2/gpu KUBERNETES_SECRET=bloodbag-dev-legacy-live-redis-v1
make kubernetes/secret/apply SITE=tirosh-home ENV_FILE=<protected-absolute-path> KUBECTX=tirosh-home/rke2/gpu KUBERNETES_SECRET=bloodbag-dev-legacy-live-policy-v1
Parent management-only seal runs after each successful apply and private validation. Root privately compares exact applied data to its custody copy and returns boolean equality. Bind that private equality check to the same observed UID and resourceVersion of that same object, and put exactly those UID and resourceVersion values in the patch. A separately fetched later resourceVersion cannot substitute. Ensure no concurrent secret writer is operating. Use one JSON patch per exact object. Do not change data, stringData, or the last-applied annotation. A test conflict aborts sealing. Repeat metadata and private validation; do not retry a patch blindly. If either seal fails, keep the pair unaccepted. Consumers remain held through the mutable interval and do not resume until both objects are validated and sealed. A lone sealed Secret is not complete custody. Do not unset immutable and do not clear immutable to retry. Reobserve BOTH immutable=true together with the expected UID, type, keys, and generation. Seal is a two-step gate and is not atomic. Do not claim Kubernetes immutability means recoverability. The safe output below prints key names only.
kubectl --context tirosh-home/rke2/gpu -n bloodbag-dev patch secret bloodbag-dev-legacy-live-redis-v1 --type=json --patch='[{"op":"test","path":"/metadata/uid","value":"<observed-uid>"},{"op":"test","path":"/metadata/resourceVersion","value":"<observed-rv>"},{"op":"add","path":"/immutable","value":true}]'
kubectl --context tirosh-home/rke2/gpu -n bloodbag-dev patch secret bloodbag-dev-legacy-live-policy-v1 --type=json --patch='[{"op":"test","path":"/metadata/uid","value":"<observed-uid>"},{"op":"test","path":"/metadata/resourceVersion","value":"<observed-rv>"},{"op":"add","path":"/immutable","value":true}]'
kubectl --context tirosh-home/rke2/gpu -n bloodbag-dev get secret bloodbag-dev-legacy-live-redis-v1 bloodbag-dev-legacy-live-policy-v1 -o go-template='{{range .items}}{{.metadata.name}} uid={{.metadata.uid}} rv={{.metadata.resourceVersion}} immutable={{.immutable}} type={{.type}} keys={{range $key, $value := .data}}{{$key}} {{end}}{{"\n"}}{{end}}'
Direct kubectl here is the documented parent seal exception for a future authorized operator. Existing env-only apply remains the provisioning API. These commands are not run by this registry change.
If a Secret is genuinely missing, restore exactly the same v1 bytes through the existing env-only apply and repeat the guarded seal before its consumers resume. Never switch mounts to a temporary name, a third Secret, or a fallback password. If a present immutable Secret is wrong, or the backup is unavailable, stop. If the backup is missing, stop that custody slice. Do not delete these objects and do not replace them under this decision. Deletion or replacement requires separate explicit authorization. This decision authorizes no deletion or in-place rotation. Lost original material without a verified backup cannot be reported recovered. Private backup retrieval and byte-for-byte comparison are a prerequisite only. An isolated create/apply/seal exercise would prove the existing mechanism, not actual dev outage recovery, and must never delete the real dev objects. No custody receipt exists yet.