From 7f297a12b66f155ae8ae28f86b88e840532365e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelo=20Gon=C3=A7alves?= Date: Wed, 16 Sep 2026 09:59:28 +0100 Subject: [PATCH 1/3] Add optional AWS web identity token for the worker Projects a Kubernetes service account token into the worker pod so it can exchange it for AWS credentials, the way IRSA does on EKS. The cluster's OIDC issuer signs the token and AWS verifies it, so nothing secret is stored. Off by default, and only the worker gets it -- connection validation runs in the engine and the blocks run there too, so the app has no need of it. Pair with OPS_AWS_WEB_IDENTITY_TOKEN_FILE and OPS_AWS_FEDERATION_ROLE_ARN in openopsEnv (openops-cloud/openops#2504). Leave disabled on EKS, where IRSA injects its own token and the AWS SDK finds it unaided. Part of OPS-4267. Co-Authored-By: Claude Opus 5 (1M context) --- chart/templates/deployment-worker.yaml | 17 +++++++++++++++++ chart/values.yaml | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/chart/templates/deployment-worker.yaml b/chart/templates/deployment-worker.yaml index a4c46e9..85521ad 100644 --- a/chart/templates/deployment-worker.yaml +++ b/chart/templates/deployment-worker.yaml @@ -71,8 +71,25 @@ spec: mountPath: /tmp/.npm - name: tmp-codes mountPath: /tmp/codes + {{- if .Values.worker.awsWebIdentity.enabled }} + - name: aws-web-identity-token + mountPath: {{ .Values.worker.awsWebIdentity.mountPath }} + readOnly: true + {{- end }} volumes: - name: npm-cache emptyDir: {} - name: tmp-codes emptyDir: {} + {{- if .Values.worker.awsWebIdentity.enabled }} + # Kubernetes signs this token and AWS verifies it against the cluster's + # OIDC issuer, returning credentials for AWS_ROLE_ARN. The same mechanism + # IRSA uses on EKS, where the token is injected for you instead. + - name: aws-web-identity-token + projected: + sources: + - serviceAccountToken: + path: token + audience: {{ .Values.worker.awsWebIdentity.audience | quote }} + expirationSeconds: {{ .Values.worker.awsWebIdentity.expirationSeconds }} + {{- end }} diff --git a/chart/values.yaml b/chart/values.yaml index 67366ff..46130c6 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -254,6 +254,16 @@ worker: create: true name: "" annotations: {} + # Exchange a projected service account token for AWS credentials, the way IRSA + # does on EKS. When enabled, also set these two in openopsEnv: + # OPS_AWS_WEB_IDENTITY_TOKEN_FILE mountPath + "/token" + # OPS_AWS_FEDERATION_ROLE_ARN the IAM role the cluster federates into + # Leave disabled on EKS: IRSA injects its own token and the AWS SDK finds it. + awsWebIdentity: + enabled: false + audience: sts.amazonaws.com + expirationSeconds: 3600 + mountPath: /var/run/secrets/aws # Prometheus metrics metrics: enabled: true From e4626873c57b18399ca6cdd315d6172406fedf12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelo=20Gon=C3=A7alves?= Date: Wed, 16 Sep 2026 10:30:30 +0100 Subject: [PATCH 2/3] Drop the explanatory comment from the volume The projected serviceAccountToken source is self-describing; values.yaml documents the feature for chart users. Part of OPS-4267. Co-Authored-By: Claude Opus 5 (1M context) --- chart/templates/deployment-worker.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/chart/templates/deployment-worker.yaml b/chart/templates/deployment-worker.yaml index 85521ad..8650d3b 100644 --- a/chart/templates/deployment-worker.yaml +++ b/chart/templates/deployment-worker.yaml @@ -82,9 +82,6 @@ spec: - name: tmp-codes emptyDir: {} {{- if .Values.worker.awsWebIdentity.enabled }} - # Kubernetes signs this token and AWS verifies it against the cluster's - # OIDC issuer, returning credentials for AWS_ROLE_ARN. The same mechanism - # IRSA uses on EKS, where the token is injected for you instead. - name: aws-web-identity-token projected: sources: From edea3851b2a69e7bc13e3e3119c491bda47329d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelo=20Gon=C3=A7alves?= Date: Wed, 16 Sep 2026 10:33:55 +0100 Subject: [PATCH 3/3] Derive the token file path in the chart The mount path and OPS_AWS_WEB_IDENTITY_TOKEN_FILE had to be kept in agreement by hand, in two different repos. Changing the mount left the app reading a path that no longer existed, surfacing as an ENOENT inside a credential provider rather than as the misconfiguration it was. The chart now emits the variable from mountPath, so the two cannot disagree. Values files supply only the role ARN. Placed before the openopsEnv block, so an explicit override still wins. Part of OPS-4267. Co-Authored-By: Claude Opus 5 (1M context) --- chart/templates/deployment-worker.yaml | 4 ++++ chart/values.yaml | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/chart/templates/deployment-worker.yaml b/chart/templates/deployment-worker.yaml index 8650d3b..ab5947b 100644 --- a/chart/templates/deployment-worker.yaml +++ b/chart/templates/deployment-worker.yaml @@ -55,6 +55,10 @@ spec: value: worker - name: OPS_CONTAINER_TYPE value: WORKER + {{- if .Values.worker.awsWebIdentity.enabled }} + - name: OPS_AWS_WEB_IDENTITY_TOKEN_FILE + value: {{ printf "%s/token" (trimSuffix "/" .Values.worker.awsWebIdentity.mountPath) | quote }} + {{- end }} {{ include "openops.renderEnv" (dict "root" . "env" .Values.openopsEnv "skipDuplicateSecrets" true) | nindent 12 }} {{ include "openops.renderEnv" (dict "root" . "env" .Values.openopsEnvSecrets) | nindent 12 }} {{ include "openops.renderEnv" (dict "root" . "env" .Values.worker.env) | nindent 12 }} diff --git a/chart/values.yaml b/chart/values.yaml index 46130c6..de5963b 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -255,9 +255,9 @@ worker: name: "" annotations: {} # Exchange a projected service account token for AWS credentials, the way IRSA - # does on EKS. When enabled, also set these two in openopsEnv: - # OPS_AWS_WEB_IDENTITY_TOKEN_FILE mountPath + "/token" - # OPS_AWS_FEDERATION_ROLE_ARN the IAM role the cluster federates into + # does on EKS. Enabling this projects the token and sets + # OPS_AWS_WEB_IDENTITY_TOKEN_FILE to match; you supply the role it federates + # into as OPS_AWS_FEDERATION_ROLE_ARN in openopsEnv. # Leave disabled on EKS: IRSA injects its own token and the AWS SDK finds it. awsWebIdentity: enabled: false