Files
homelab/kubernetes/infrastructure/openbao/rotation/ha-config-sync.yaml
T
hermes-bot 6f1a7b6d96
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
fix(secret-rotator): never fail the HA run after the store; stage the image rollout
Folds the good parts of #1412 into this PR and addresses both review-bot
reviews (#1412 review 1789, #1414 review 1791):

- Everything after the OpenBao store is best-effort. Decode, reconnect,
  listing and revokes run in reap_superseded(); reap_summary() turns any
  error into "reap skipped" plus a warning, so rotate_ha_token returns Ok.
  A failed run would start a second pod (backoffLimit: 1) that keeps the
  token just stored and its successor and reaps the token consumers still
  hold until ESO syncs, i.e. the #1081 outage. Two unit tests cover it.
- Warn when the replaced token is not named "<client_name> [<6 hex>]":
  no later run reaps it, so it needs a manual revoke (from #1412).
- Staged image rollout (from #1412): only the three HA CronJobs carry the
  flux-system:secret-rotator marker; the other 17 rotators stay on
  2026-07-30 until a manual HA run validates the new binary, then a
  follow-up adds the marker to them. rotation/kustomization.yaml records
  the exception.
- Merged current main (a6f37e2b, 1691a0ac): the Reloader annotations for
  zone-configurator and speech-to-phrase are already there via #1409.
2026-10-21 07:59:52 +00:00

90 lines
3.2 KiB
YAML

---
# Rotate the `ha-config-sync` Gitea PAT (write:repository). ha-config-sync is a
# write collaborator on the homeassistant repo; the config-sync sidecar
# (apps/home-assistant) pushes the `live` branch and opens the live -> main PR
# with it. ESO syncs the token into Secret home-assistant-config-sync-gitea.
#
# `rotate-mint` — secret-rotator gitea-token: mint the PAT, verify it can pull
# AND push homeassistant, store it at infrastructure/ha-config-sync#token,
# reap old tokens keeping the two newest.
#
# Policy/role rotator-ha-config-sync and the bootstraps are provisioned by hand —
# see policies/rotator-ha-config-sync.hcl. Netpol halves:
# gitea-allow-ha-config-sync-rotator, rotator-ha-config-sync-egress.
apiVersion: v1
kind: ServiceAccount
metadata:
name: ha-config-sync-secret-rotator
namespace: openbao
labels:
app.kubernetes.io/name: ha-config-sync
app.kubernetes.io/component: secret-rotator
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ha-config-sync-secret-rotate
namespace: openbao
labels:
app.kubernetes.io/name: ha-config-sync
app.kubernetes.io/component: secret-rotator
spec:
suspend: false
schedule: "30 4 1 1,4,7,10 *" # quarterly, Europe/Berlin
timeZone: Europe/Berlin
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 2
failedJobsHistoryLimit: 5
startingDeadlineSeconds: 3600
jobTemplate:
spec:
backoffLimit: 1
activeDeadlineSeconds: 300
ttlSecondsAfterFinished: 259200 # 3 d
template:
metadata:
labels:
app.kubernetes.io/name: ha-config-sync
app.kubernetes.io/component: secret-rotator
spec:
serviceAccountName: ha-config-sync-secret-rotator
restartPolicy: Never
securityContext:
runAsNonRoot: true
runAsUser: 65534
runAsGroup: 65534
seccompProfile:
type: RuntimeDefault
containers:
- name: rotate-mint
image: gitea.renner.uno/gitea_admin/secret-rotator:2026-07-30
args: ["gitea-token"]
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
env:
- name: BAO_ADDR
value: http://openbao.openbao.svc.cluster.local:8200
- name: BAO_ROLE
value: rotator-ha-config-sync
- name: BOOTSTRAP_PATH
value: homelab/infrastructure/secret-rotators-bootstrap/ha-config-sync
- name: BAO_PATH
value: homelab/infrastructure/ha-config-sync
- name: GITEA_URL
value: http://gitea.gitea.svc.cluster.local:3000
- name: GITEA_VERIFY_REPO
value: konairius/homeassistant
- name: GITEA_SCOPES
value: write:repository
- name: GITEA_TOKEN_NAME_PREFIX
value: ha-config-sync-rotated
resources:
requests:
cpu: 25m
memory: 16Mi
limits:
memory: 48Mi