From d49080d1b1453f57f88e3eeca5baf49af1683fd0 Mon Sep 17 00:00:00 2001 From: Entlein Date: Tue, 23 Jun 2026 00:42:04 +0200 Subject: [PATCH] feat(ae-control): TLS on the control surface (CONTROL_TLS) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Auth without TLS is half a control: tcpdump on dx→AE :9100 captured 720 cleartext `Authorization: Bearer` JWTs in 70s — the #68 token crosses the CNI in plaintext. CONTROL_TLS=true now serves TLS with server.crt/key from the service-tls-certs secret (broker/PEM already use it; dx skip-verifies). Default-OFF for incremental rollout, symmetric to CONTROL_REQUIRE_AUTH. Stacks on #68 (ae-followup-auth). dx client half: entlein/dx#88. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../bootstrap/adaptive_export_deployment.yaml | 11 +++++++++ .../services/adaptive_export/cmd/main.go | 23 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/k8s/vizier/bootstrap/adaptive_export_deployment.yaml b/k8s/vizier/bootstrap/adaptive_export_deployment.yaml index 19f52a640f3..2db195ff408 100644 --- a/k8s/vizier/bootstrap/adaptive_export_deployment.yaml +++ b/k8s/vizier/bootstrap/adaptive_export_deployment.yaml @@ -88,6 +88,13 @@ spec: # value: "changeme-ingest" # - name: CLICKHOUSE_DATABASE # value: "forensic_db" + # TLS for the control surface (CONTROL_TLS=true). server.crt/key from the + # same service-tls-certs secret the broker/PEM use; without this the dx + # bearer JWT crosses the CNI in cleartext. Harmless when control is off. + volumeMounts: + - name: certs + mountPath: /certs + readOnly: true securityContext: allowPrivilegeEscalation: false capabilities: @@ -95,6 +102,10 @@ spec: - ALL seccompProfile: type: RuntimeDefault + volumes: + - name: certs + secret: + secretName: service-tls-certs securityContext: runAsUser: 10100 runAsGroup: 10100 diff --git a/src/vizier/services/adaptive_export/cmd/main.go b/src/vizier/services/adaptive_export/cmd/main.go index 7cb5ae6d1ee..eca049ec7ca 100644 --- a/src/vizier/services/adaptive_export/cmd/main.go +++ b/src/vizier/services/adaptive_export/cmd/main.go @@ -600,8 +600,27 @@ func main() { } go func() { log.WithField("addr", addr).Info("control surface listening") - if err := httpSrv.ListenAndServe(); err != nil && - err != http.ErrServerClosed { + // CONTROL_TLS=true → serve TLS so the bearer JWT + control payloads + // don't cross the CNI in cleartext (auth without TLS leaks the token). + // Cert/key from the service-tls-certs secret the broker/PEM already use + // (mounted /certs); dx skip-verifies. Default-OFF for incremental rollout. + var err error + if os.Getenv("CONTROL_TLS") == "true" { + cert := os.Getenv("CONTROL_TLS_CERT") + if cert == "" { + cert = "/certs/server.crt" + } + key := os.Getenv("CONTROL_TLS_KEY") + if key == "" { + key = "/certs/server.key" + } + log.WithField("cert", cert).Info("control surface: TLS ENABLED") + err = httpSrv.ListenAndServeTLS(cert, key) + } else { + log.Warn("control surface: TLS DISABLED — bearer JWT crosses the CNI in cleartext (set CONTROL_TLS=true)") + err = httpSrv.ListenAndServe() + } + if err != nil && err != http.ErrServerClosed { log.WithError(err).Error("control surface stopped") } }()