Merge forgejo/master into wizard/errorpages-buffer
Some checks failed
ci/woodpecker/push/default Pipeline was canceled
ci/woodpecker/push/build-cli Pipeline was canceled

This commit is contained in:
Viktor Barzin 2026-06-12 20:31:22 +00:00
commit f3cb5661a6
2 changed files with 95 additions and 30 deletions

View file

@ -0,0 +1,89 @@
# =============================================================================
# ghcr.io pull credentials synced ONLY to namespaces running PRIVATE ghcr
# images (ADR-0002 off-infra builds)
# =============================================================================
# The credential is Viktor's admin PAT (Vault secret/viktor/ghcr_pull_token
# an alias of github_pat: GitHub has no API to mint tokens, so a UI-minted
# read:packages token can replace the alias value later with no TF change).
# Because the PAT is broad, this is a positive allowlist, NOT cluster-wide
# like registry-credentials: any workload in a listed namespace can read the
# secret, so every entry widens the blast radius. Public-image namespaces
# need no credentials keep this list to private-image consumers only.
locals {
ghcr_private_namespaces = [
"tripit",
"f1-stream",
"job-hunter",
"instagram-poster",
"payslip-ingest",
"wealthfolio",
"fire-planner",
"recruiter-responder",
]
}
resource "kubernetes_secret" "ghcr_credentials" {
metadata {
name = "ghcr-credentials"
namespace = kubernetes_namespace.kyverno.metadata[0].name
}
type = "kubernetes.io/dockerconfigjson"
data = {
".dockerconfigjson" = jsonencode({
auths = {
"ghcr.io" = {
username = "ViktorBarzin"
password = try(data.vault_kv_secret_v2.viktor.data["ghcr_pull_token"], "")
auth = base64encode("ViktorBarzin:${try(data.vault_kv_secret_v2.viktor.data["ghcr_pull_token"], "")}")
}
}
})
}
}
resource "kubectl_manifest" "sync_ghcr_credentials" {
yaml_body = yamlencode({
apiVersion = "kyverno.io/v1"
kind = "ClusterPolicy"
metadata = {
name = "sync-ghcr-credentials"
}
spec = {
rules = [
{
name = "sync-ghcr-secret"
match = {
any = [
{
resources = {
kinds = ["Namespace"]
names = local.ghcr_private_namespaces
}
}
]
}
generate = {
generateExisting = true
apiVersion = "v1"
kind = "Secret"
name = "ghcr-credentials"
namespace = "{{request.object.metadata.name}}"
synchronize = true
clone = {
namespace = "kyverno"
name = "ghcr-credentials"
}
}
}
]
}
})
depends_on = [
helm_release.kyverno,
kubernetes_secret.ghcr_credentials,
kubernetes_cluster_role_binding.kyverno_admission_secret_manager,
kubernetes_cluster_role_binding.kyverno_background_secret_manager,
]
}

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"