kyverno: sync-ghcr-credentials to private-ghcr namespaces; tripit consumes the clone
All checks were successful
ci/woodpecker/push/default Pipeline was successful
ci/woodpecker/push/build-cli Pipeline was successful

Viktor asked to unblock the ADR-0002 ghcr pull-secret work (infra#12)
without waiting on a UI-minted token: GitHub has no token-mint API, so
the admin PAT (aliased in Vault as secret/viktor/ghcr_pull_token —
swap the alias value when a scoped token is ever minted) becomes the
platform credential. Because the PAT is broad, the new ClusterPolicy
clones ghcr-credentials ONLY to an explicit allowlist of namespaces
running private ghcr images (tripit, f1-stream, job-hunter,
instagram-poster, payslip-ingest, wealthfolio, fire-planner,
recruiter-responder) — NOT cluster-wide like registry-credentials.
generateExisting+synchronize so existing namespaces get the clone.
tripit's hand-declared ns-scoped secret is removed in favour of the
clone (imagePullSecrets now reference the name literally).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-06-12 20:28:11 +00:00
parent 12fd1fcbc9
commit 523e18c127
2 changed files with 95 additions and 30 deletions

View file

@ -142,34 +142,10 @@ resource "kubernetes_namespace" "tripit" {
}
}
# GHCR pull secret (tripit ns only) for the private ghcr.io/viktorbarzin/tripit image
# now built off-infra by GitHub Actions. Uses viktor's github_pat as the pull
# credential admin-scoped, accepted as an interim (rotate to a fine-grained
# read:packages token later). Scoped to this namespace to limit the broad token's
# blast radius (deliberately NOT folded into the cluster-wide registry-credentials).
data "vault_kv_secret_v2" "viktor" {
mount = "secret"
name = "viktor"
}
resource "kubernetes_secret" "ghcr_credentials" {
metadata {
name = "ghcr-credentials"
namespace = kubernetes_namespace.tripit.metadata[0].name
}
type = "kubernetes.io/dockerconfigjson"
data = {
".dockerconfigjson" = jsonencode({
auths = {
"ghcr.io" = {
username = "ViktorBarzin"
password = data.vault_kv_secret_v2.viktor.data["github_pat"]
auth = base64encode("ViktorBarzin:${data.vault_kv_secret_v2.viktor.data["github_pat"]}")
}
}
})
}
}
# GHCR pull secret: the ghcr-credentials Secret in this namespace is cloned in
# by the kyverno stack's sync-ghcr-credentials ClusterPolicy (allowlisted
# private-ghcr namespaces only ADR-0002). Source of truth:
# stacks/kyverno/modules/kyverno/ghcr-credentials.tf.
# App secrets seed these in Vault before applying:
# secret/tripit
@ -370,7 +346,7 @@ resource "kubernetes_deployment" "tripit" {
name = "registry-credentials"
}
image_pull_secrets {
name = kubernetes_secret.ghcr_credentials.metadata[0].name
name = "ghcr-credentials"
}
init_container {
@ -650,7 +626,7 @@ resource "kubernetes_cron_job_v1" "tripit_worker" {
name = "registry-credentials"
}
image_pull_secrets {
name = kubernetes_secret.ghcr_credentials.metadata[0].name
name = "ghcr-credentials"
}
container {
name = "worker"