diff --git a/stacks/mailserver/main.tf b/stacks/mailserver/main.tf index da131f8d..bff786cc 100644 --- a/stacks/mailserver/main.tf +++ b/stacks/mailserver/main.tf @@ -11,11 +11,6 @@ data "vault_kv_secret_v2" "secrets" { name = "platform" } -data "vault_kv_secret_v2" "viktor" { - mount = "secret" - name = "viktor" -} - locals { mailserver_accounts = jsondecode(data.vault_kv_secret_v2.secrets.data["mailserver_accounts"]) mailserver_aliases = jsondecode(data.vault_kv_secret_v2.secrets.data["mailserver_aliases"]) @@ -24,16 +19,14 @@ locals { } module "mailserver" { - source = "./modules/mailserver" - tls_secret_name = var.tls_secret_name - nfs_server = var.nfs_server - mysql_host = var.mysql_host - mailserver_accounts = local.mailserver_accounts - postfix_account_aliases = local.mailserver_aliases - opendkim_key = local.mailserver_opendkim_key - sasl_passwd = local.mailserver_sasl_passwd - roundcube_db_password = data.vault_kv_secret_v2.secrets.data["mailserver_roundcubemail_db_password"] - tier = local.tiers.edge - brevo_api_key = jsondecode(base64decode(data.vault_kv_secret_v2.viktor.data["brevo_api_key"]))["api_key"] - email_monitor_imap_password = local.mailserver_accounts["spam@viktorbarzin.me"] + source = "./modules/mailserver" + tls_secret_name = var.tls_secret_name + nfs_server = var.nfs_server + mysql_host = var.mysql_host + mailserver_accounts = local.mailserver_accounts + postfix_account_aliases = local.mailserver_aliases + opendkim_key = local.mailserver_opendkim_key + sasl_passwd = local.mailserver_sasl_passwd + roundcube_db_password = data.vault_kv_secret_v2.secrets.data["mailserver_roundcubemail_db_password"] + tier = local.tiers.edge } diff --git a/stacks/mailserver/modules/mailserver/main.tf b/stacks/mailserver/modules/mailserver/main.tf index 06d8f815..c3b7bd91 100644 --- a/stacks/mailserver/modules/mailserver/main.tf +++ b/stacks/mailserver/modules/mailserver/main.tf @@ -5,15 +5,6 @@ variable "postfix_account_aliases" {} variable "opendkim_key" {} variable "sasl_passwd" {} # For sendgrid i.e relayhost variable "nfs_server" { type = string } -variable "brevo_api_key" { - type = string - sensitive = true -} -variable "email_monitor_imap_password" { - type = string - sensitive = true -} - # Build the virtual-alias map, dropping aliases where BOTH the source and # target are real mailboxes in var.mailserver_accounts (and are different). # Without this filter, docker-mailserver emits two passwd-file userdb lines @@ -564,6 +555,61 @@ resource "kubernetes_service" "mailserver" { # E2E Email Roundtrip Monitor # Sends test email via Brevo API, verifies delivery via IMAP, pushes metrics # ============================================================================= +# ExternalSecret syncing the probe's Vault inputs into a K8s Secret, so +# `kubectl describe cronjob email-roundtrip-monitor` no longer leaks the +# Brevo API key and IMAP password via `env[].value`. The two upstream Vault +# entries both wrap the effective secret: +# - secret/viktor → brevo_api_key = base64(JSON({"api_key": "..."})) +# - secret/platform → mailserver_accounts = JSON({"spam@viktorbarzin.me": "", ...}) +# ESO's `target.template` (engineVersion v2) runs sprig on the raw remote +# values so the rendered K8s Secret contains ONLY the two env vars the probe +# actually needs, under the exact keys `BREVO_API_KEY` and +# `EMAIL_MONITOR_IMAP_PASSWORD` so the CronJob can consume them via a single +# `env_from { secret_ref {} }` block. +resource "kubernetes_manifest" "email_roundtrip_monitor_secrets" { + manifest = { + apiVersion = "external-secrets.io/v1beta1" + kind = "ExternalSecret" + metadata = { + name = "mailserver-probe-secrets" + namespace = kubernetes_namespace.mailserver.metadata[0].name + } + spec = { + refreshInterval = "15m" + secretStoreRef = { + name = "vault-kv" + kind = "ClusterSecretStore" + } + target = { + name = "mailserver-probe-secrets" + template = { + engineVersion = "v2" + data = { + BREVO_API_KEY = "{{ .brevo_api_key_wrapped | b64dec | fromJson | dig \"api_key\" \"\" }}" + EMAIL_MONITOR_IMAP_PASSWORD = "{{ .mailserver_accounts | fromJson | dig \"spam@viktorbarzin.me\" \"\" }}" + } + } + } + data = [ + { + secretKey = "brevo_api_key_wrapped" + remoteRef = { + key = "viktor" + property = "brevo_api_key" + } + }, + { + secretKey = "mailserver_accounts" + remoteRef = { + key = "platform" + property = "mailserver_accounts" + } + }, + ] + } + } +} + resource "kubernetes_cron_job_v1" "email_roundtrip_monitor" { metadata { name = "email-roundtrip-monitor" @@ -695,13 +741,10 @@ sys.exit(0 if success else 1) ' EOT ] - env { - name = "BREVO_API_KEY" - value = var.brevo_api_key - } - env { - name = "EMAIL_MONITOR_IMAP_PASSWORD" - value = var.email_monitor_imap_password + env_from { + secret_ref { + name = "mailserver-probe-secrets" + } } resources { requests = {