diff --git a/kubernetes/apps/authentik/hetzner-creds-externalsecret.yaml b/kubernetes/apps/authentik/hetzner-creds-externalsecret.yaml index 256aa150..1cb48153 100644 --- a/kubernetes/apps/authentik/hetzner-creds-externalsecret.yaml +++ b/kubernetes/apps/authentik/hetzner-creds-externalsecret.yaml @@ -15,4 +15,4 @@ spec: name: hetzner-s3-creds # keeps the old Secret's name — consumers unchanged dataFrom: - extract: - key: seed/authentik/hetzner-creds + key: infrastructure/hetzner-s3 diff --git a/kubernetes/apps/home-assistant/ha-pg-hetzner-creds-externalsecret.yaml b/kubernetes/apps/home-assistant/ha-pg-hetzner-creds-externalsecret.yaml index 2f666186..f097ff23 100644 --- a/kubernetes/apps/home-assistant/ha-pg-hetzner-creds-externalsecret.yaml +++ b/kubernetes/apps/home-assistant/ha-pg-hetzner-creds-externalsecret.yaml @@ -1,21 +1,14 @@ --- # Barman S3 credentials for ha-pg. # -# FOLLOW-UP (#397): sourced from seed/paperless/hetzner-creds, which is not where -# they belong. woodpecker/hetzner-creds-externalsecret.yaml has the identical -# problem and the same note. The values are the same today, so this is correct -# but coupled: rotating paperless's Hetzner credentials would silently change -# the backup credentials for Home Assistant and Woodpecker too. +# One shared path for one shared credential — see the note in +# ../paperless/hetzner-creds-externalsecret.yaml. # -# The fix is one dedicated path per consumer (seed/home-assistant/hetzner-creds) -# and a one-line change to the `key:` below. Creating it needs an OpenBao write: -# -# bao kv put homelab/seed/home-assistant/hetzner-creds \ -# @<(bao kv get -format=json homelab/seed/paperless/hetzner-creds | jq '.data.data') -# -# Note the mount is `homelab`, so the path is homelab/seed/... — #397 records a -# 403 on `bao kv list seed`, which was a wrong-path error rather than a -# permissions problem. +# The earlier note here proposed a dedicated seed/home-assistant path. That was +# the wrong direction: it would have made a fifth copy of the same key look like +# a fourth independent credential. It did get one thing right, and it is worth +# keeping: the 403 recorded in #397 was a wrong-path error, not a permissions +# problem, because the mount is `homelab` and the path is homelab/seed/... # # The namespace allowlist on the openbao ClusterSecretStore # (infrastructure/post-crds/openbao-clustersecretstore.yaml) must include this @@ -35,4 +28,4 @@ spec: name: hetzner-s3-creds dataFrom: - extract: - key: seed/paperless/hetzner-creds + key: infrastructure/hetzner-s3 diff --git a/kubernetes/apps/immich/hetzner-creds-externalsecret.yaml b/kubernetes/apps/immich/hetzner-creds-externalsecret.yaml index ccb23e84..521cd9a4 100644 --- a/kubernetes/apps/immich/hetzner-creds-externalsecret.yaml +++ b/kubernetes/apps/immich/hetzner-creds-externalsecret.yaml @@ -15,4 +15,4 @@ spec: name: hetzner-s3-creds # keeps the old Secret's name — consumers unchanged dataFrom: - extract: - key: seed/immich/hetzner-creds + key: infrastructure/hetzner-s3 diff --git a/kubernetes/apps/paperless/hetzner-creds-externalsecret.yaml b/kubernetes/apps/paperless/hetzner-creds-externalsecret.yaml index e547d073..0c39a497 100644 --- a/kubernetes/apps/paperless/hetzner-creds-externalsecret.yaml +++ b/kubernetes/apps/paperless/hetzner-creds-externalsecret.yaml @@ -1,3 +1,27 @@ +# CANONICAL NOTE on the Hetzner S3 credentials. The other consumers point here +# rather than repeating it. +# +# There is exactly ONE Hetzner S3 key, and every barman ObjectStore in this +# cluster uses it. It used to live under four paths — seed/paperless, +# seed/authentik, seed/immich, seed/trmnl — with byte-identical contents, +# verified by comparing SHA-256 fingerprints of the synced Secrets rather than +# by reading them. The same key also sits in infrastructure/velero-hetzner, in +# a different shape (a single `cloud` field holding an AWS credentials file); +# its access key id fingerprints the same. +# +# Per-app paths implied a separation that did not exist. Rotating the key at +# Hetzner changes it for everyone regardless of how many paths hold a copy, so +# the separate paths bought nothing and cost a standing invitation to believe +# otherwise — #397 was opened on exactly that misreading, proposing to give +# woodpecker a fifth copy. +# +# Real separation needs one Hetzner key per consumer, and Hetzner keys can only +# be created by hand in their console. Until someone wants that, one path is the +# honest representation. +# +# Not yet folded in: velero. It needs the credentials file form, so moving it +# here means templating the INI from these fields — worth doing, not worth +# bundling with a path swap that touches every database backup. apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: @@ -15,4 +39,4 @@ spec: name: hetzner-s3-creds # keeps the old Secret's name — consumers unchanged dataFrom: - extract: - key: seed/paperless/hetzner-creds + key: infrastructure/hetzner-s3 diff --git a/kubernetes/apps/trmnl/hetzner-creds-externalsecret.yaml b/kubernetes/apps/trmnl/hetzner-creds-externalsecret.yaml index 6a9a2775..c7cf88ef 100644 --- a/kubernetes/apps/trmnl/hetzner-creds-externalsecret.yaml +++ b/kubernetes/apps/trmnl/hetzner-creds-externalsecret.yaml @@ -12,4 +12,4 @@ spec: name: hetzner-s3-creds dataFrom: - extract: - key: seed/trmnl/hetzner-creds + key: infrastructure/hetzner-s3 diff --git a/kubernetes/apps/woodpecker/hetzner-creds-externalsecret.yaml b/kubernetes/apps/woodpecker/hetzner-creds-externalsecret.yaml index 281982cd..aa8a26d0 100644 --- a/kubernetes/apps/woodpecker/hetzner-creds-externalsecret.yaml +++ b/kubernetes/apps/woodpecker/hetzner-creds-externalsecret.yaml @@ -1,11 +1,8 @@ --- # Barman S3 credentials for wp-pg. # -# Sourced from seed/paperless/hetzner-creds, which is not where they belong. -# Issue #397 wants woodpecker to own seed/woodpecker/hetzner-creds; creating -# that path needs OpenBao write access (`bao kv list seed` → 403 for the -# identities available here), so it stays open. The values are identical, so it -# is a one-line swap of the `key:` below once the path exists. +# One shared path for one shared credential — see the note in +# ../paperless/hetzner-creds-externalsecret.yaml. # # The namespace allowlist on the openbao ClusterSecretStore # (infrastructure/post-crds/openbao-clustersecretstore.yaml) must include this @@ -24,4 +21,4 @@ spec: name: hetzner-s3-creds dataFrom: - extract: - key: seed/paperless/hetzner-creds + key: infrastructure/hetzner-s3 diff --git a/kubernetes/apps/wordpress/externalsecret.yaml b/kubernetes/apps/wordpress/externalsecret.yaml index 2698aabd..a8640df6 100644 --- a/kubernetes/apps/wordpress/externalsecret.yaml +++ b/kubernetes/apps/wordpress/externalsecret.yaml @@ -36,11 +36,9 @@ spec: target: name: hetzner-s3-creds dataFrom: - # Reuses the paperless copy of the shared Hetzner S3 credentials (identical - # ACCESS_KEY_ID / ACCESS_SECRET_KEY / REGION) to avoid seeding a new OpenBao - # path for this migration — same approach woodpecker took. FOLLOW-UP: give - # wordpress its own seed/wordpress/hetzner-creds path once OpenBao can be - # written, and repoint this here (the value is the same, so it's a drop-in - # swap). + # One shared path for one shared credential. There is a single Hetzner S3 + # key behind all of these — see the note in + # ../paperless/hetzner-creds-externalsecret.yaml for why per-app paths were + # the wrong shape and what would have to change for them to be right. - extract: - key: seed/paperless/hetzner-creds + key: infrastructure/hetzner-s3