diff --git a/.gitleaksignore b/.gitleaksignore new file mode 100644 index 00000000..dfe626cd --- /dev/null +++ b/.gitleaksignore @@ -0,0 +1,4 @@ +# git-crypt encrypts these at rest; the working-tree plaintext is local-only. +# gitleaks scans the staged working-tree copy and can't see that they're +# encrypted on disk in git, so allowlist by fingerprint. +stacks/recruiter-responder/secrets/privkey.pem:private-key:1 diff --git a/stacks/recruiter-responder/main.tf b/stacks/recruiter-responder/main.tf index cbc74a7f..6958eb50 100644 --- a/stacks/recruiter-responder/main.tf +++ b/stacks/recruiter-responder/main.tf @@ -6,6 +6,11 @@ variable "image_tag" { variable "postgresql_host" { type = string } +variable "tls_secret_name" { + type = string + sensitive = true +} + locals { namespace = "recruiter-responder" image = "forgejo.viktorbarzin.me/viktor/recruiter-responder:${var.image_tag}" @@ -243,6 +248,12 @@ resource "kubernetes_deployment" "recruiter_responder" { value = "http://claude-agent-service.claude-agent.svc.cluster.local:8080" } # Telegram bot (no URL env needed — token in secret) + # Public callback base URL for inline-keyboard URL buttons. + # Must match the ingress host below (proxied via Cloudflare). + env { + name = "CALLBACK_BASE_URL" + value = "https://recruiter-responder.viktorbarzin.me" + } readiness_probe { http_get { @@ -298,3 +309,27 @@ resource "kubernetes_service" "recruiter_responder" { } } } + +# Kyverno ClusterPolicy `sync-tls-secret` auto-clones the wildcard TLS +# secret into every namespace, so we don't need a setup_tls_secret module. + +# Public ingress for the /cb/* callback endpoints driven by Telegram URL +# buttons. /api/* and /healthz stay internal — they're routed via cluster +# DNS from the OpenClaw plugin / kubelet probes respectively. +# +# auth = "none": the /cb endpoints are gated by HMAC-signed query params +# (sig + exp) generated from WEBHOOK_BEARER_TOKEN. Authentik would force +# a login flow before the GET could fire and break the one-tap flow. +module "ingress" { + source = "../../modules/kubernetes/ingress_factory" + # auth = "none": HMAC + expiry gate the /cb endpoints — Authentik would + # force a login dance and break Telegram's one-tap UX. See callback_links.py. + auth = "none" + anti_ai_scraping = false + dns_type = "proxied" + namespace = kubernetes_namespace.recruiter_responder.metadata[0].name + name = "recruiter-responder" + port = 8080 + ingress_path = ["/cb"] + tls_secret_name = var.tls_secret_name +} diff --git a/stacks/recruiter-responder/secrets/fullchain.pem b/stacks/recruiter-responder/secrets/fullchain.pem new file mode 100644 index 00000000..b0dcf470 Binary files /dev/null and b/stacks/recruiter-responder/secrets/fullchain.pem differ diff --git a/stacks/recruiter-responder/secrets/privkey.pem b/stacks/recruiter-responder/secrets/privkey.pem new file mode 100644 index 00000000..444b348e Binary files /dev/null and b/stacks/recruiter-responder/secrets/privkey.pem differ diff --git a/stacks/recruiter-responder/terragrunt.hcl b/stacks/recruiter-responder/terragrunt.hcl index 6a27cb7a..182796e7 100644 --- a/stacks/recruiter-responder/terragrunt.hcl +++ b/stacks/recruiter-responder/terragrunt.hcl @@ -19,5 +19,5 @@ dependency "external-secrets" { inputs = { # Override per-deploy in CI / commit. - image_tag = "0500c3d3" + image_tag = "7383b426" }