From ea5c24a7df0d8649afcdf9ac0f6ba432090055ef Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 16 Jul 2026 10:46:52 -0400 Subject: [PATCH 1/9] feat: sysdig registry-scanner use managedIdentity for ACR --- charts/registry-scanner/Chart.yaml | 10 ++-- .../registry-scanner/templates/_helpers.tpl | 10 ++++ charts/registry-scanner/templates/_job.tpl | 55 +++++++++++++++++++ charts/registry-scanner/templates/secret.yaml | 3 +- charts/registry-scanner/values.yaml | 11 ++++ 5 files changed, 83 insertions(+), 6 deletions(-) diff --git a/charts/registry-scanner/Chart.yaml b/charts/registry-scanner/Chart.yaml index 51a0178fb..342a2beab 100644 --- a/charts/registry-scanner/Chart.yaml +++ b/charts/registry-scanner/Chart.yaml @@ -1,10 +1,10 @@ apiVersion: v2 -name: registry-scanner +appVersion: 0.12.1 description: Sysdig Registry Scanner -type: application home: https://www.sysdig.com/ icon: https://avatars.githubusercontent.com/u/5068817?s=200&v=4 -version: 1.11.1 -appVersion: 0.12.1 maintainers: - - name: sysdiglabs +- name: sysdiglabs +name: registry-scanner +type: application +version: 1.11.1 diff --git a/charts/registry-scanner/templates/_helpers.tpl b/charts/registry-scanner/templates/_helpers.tpl index de551ea03..f8a12e876 100644 --- a/charts/registry-scanner/templates/_helpers.tpl +++ b/charts/registry-scanner/templates/_helpers.tpl @@ -130,6 +130,16 @@ Allow overriding registry and repository for air-gapped environments {{- end -}} {{- end -}} +{{/* +Init container image for AAD token fetcher (ACR workload identity) +*/}} +{{- define "registry-scanner.initContainerImage" -}} +{{- $initRegistry := .Values.image.initContainerRegistry | default .Values.image.registry | default "quay.io" -}} +{{- $initRepository := .Values.image.initContainerRepository | default "library/curl" -}} +{{- $initTag := .Values.image.initContainerTag | default "7.85.0" -}} +{{- printf "%s/%s:%s" $initRegistry $initRepository $initTag -}} +{{- end -}} + {{- define "registry-scanner.rawPullSecretList" -}} {{- range .Values.imagePullSecrets }}{{- if . }}{{- .name}},{{- end}}{{- end}} {{- end -}} diff --git a/charts/registry-scanner/templates/_job.tpl b/charts/registry-scanner/templates/_job.tpl index 949620879..03ea70811 100644 --- a/charts/registry-scanner/templates/_job.tpl +++ b/charts/registry-scanner/templates/_job.tpl @@ -21,6 +21,45 @@ serviceAccountName: {{ include "registry-scanner.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 12 }} + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + initContainers: + - name: aad-token-fetcher + image: {{ include "registry-scanner.initContainerImage" . }} + imagePullPolicy: {{ .Values.image.initContainerPullPolicy | default .Values.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + set -e + # Fetch AAD token from IMDS for ACR + REGISTRY_URL="{{ .Values.config.registryURL }}" + ENDPOINT="http://169.254.169.254/metadata/identity/oauth2/token?api-version=2017-09-01&resource=https://${REGISTRY_URL}" + + MAX_RETRIES=5 + RETRY_COUNT=0 + while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do + if TOKEN=$(curl -s -H "Metadata:true" "$ENDPOINT" 2>/dev/null | grep -o '"access_token":"[^"]*' | cut -d'"' -f4); then + if [ -n "$TOKEN" ]; then + echo "$TOKEN" > /aad-token/token + echo "AAD token fetched successfully" + exit 0 + fi + fi + RETRY_COUNT=$((RETRY_COUNT + 1)) + if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then + echo "Retrying IMDS token fetch ($RETRY_COUNT/$MAX_RETRIES)..." + sleep 2 + fi + done + echo "Failed to fetch AAD token after $MAX_RETRIES attempts" + exit 1 + volumeMounts: + - name: aad-token + mountPath: /aad-token + securityContext: + runAsNonRoot: true + runAsUser: 65534 + {{- end }} containers: - name: {{ .Chart.Name }} securityContext: @@ -34,6 +73,10 @@ - name: config-volume mountPath: /config.yaml subPath: config.yaml + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + - name: aad-token + mountPath: /aad-token + {{- end }} {{- if .Values.reportToPersistentVolumeClaim }} - name: report-storage mountPath: "/output" @@ -120,6 +163,9 @@ key: registryUser {{- if ne .Values.config.registryType "ocp" }} - name: REGISTRYSCANNER_REGISTRY_PASSWORD + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + value: "" + {{- else }} valueFrom: secretKeyRef: {{- if not .Values.existingSecretName }} @@ -128,6 +174,11 @@ name: {{ .Values.existingSecretName }} {{- end }} key: registryPassword + {{- end }} + {{- end }} + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + - name: REGISTRYSCANNER_REGISTRY_PASSWORD_FILE + value: /aad-token/token {{- end }} {{- end }} {{ if .Values.config.parallelGoRoutines }} @@ -160,6 +211,10 @@ - name: config-volume configMap: name: {{ include "registry-scanner.fullname" . }} + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + - name: aad-token + emptyDir: {} + {{- end }} {{- if .Values.ssl.ca.certs }} - name: ca-certs projected: diff --git a/charts/registry-scanner/templates/secret.yaml b/charts/registry-scanner/templates/secret.yaml index 952e189d9..5abba14d6 100644 --- a/charts/registry-scanner/templates/secret.yaml +++ b/charts/registry-scanner/templates/secret.yaml @@ -20,9 +20,10 @@ data: registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- else if eq .Values.config.registryType "ocp" }} registryUser: {{ "serviceaccount"| b64enc | quote }} + {{- else if not (and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity) }} + registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- else }} registryUser: {{ required "A valid .Values.config.registryUser is required" .Values.config.registryUser | b64enc | quote }} - registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- end }} {{- end }} {{- range $index, $cert := .Values.ssl.ca.certs }} diff --git a/charts/registry-scanner/values.yaml b/charts/registry-scanner/values.yaml index 12512dd05..57c5e79ed 100644 --- a/charts/registry-scanner/values.yaml +++ b/charts/registry-scanner/values.yaml @@ -30,6 +30,9 @@ config: registryPassword: "" # **required**
The registry Type. Supported types: artifactory, ecr, icr, acr, quay, harbor, gar, gcr, nexus, ocp and dockerv2. registryType: "" + # Use Azure workload identity (AAD token) instead of username/password for ACR authentication. + # Requires registryType to be 'acr' and the pod to have azure.workload.identity annotations. + acr_workloadidentity: false # The account ID. Applicable only for ICR registry type. registryAccountId: "" # The ICR IAM API. Applicable only for ICR registry type. @@ -180,6 +183,14 @@ image: pullPolicy: Always # Whether or not to use a Federal Information Processing Standard (FIPS) compliant image. fips: false + # Init container image registry for AAD token fetcher (when registryType is acr). Defaults to the main image registry. + initContainerRegistry: "" + # Init container image repository for AAD token fetcher. Defaults to library/curl on the main registry. + initContainerRepository: "library/curl" + # Init container image tag. Defaults to 7.85.0 + initContainerTag: "7.85.0" + # Init container pull policy. Defaults to the main pullPolicy. + initContainerPullPolicy: "" serviceAccount: # Specifies whether a service account should be created. From ee13546d499689cd27e1f91eb333f53e7b313617 Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 16 Jul 2026 10:57:46 -0400 Subject: [PATCH 2/9] docs: update README and values --- charts/registry-scanner/README.md | 1 + charts/registry-scanner/values.yaml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/charts/registry-scanner/README.md b/charts/registry-scanner/README.md index c8c4d1040..86e4fa0fc 100644 --- a/charts/registry-scanner/README.md +++ b/charts/registry-scanner/README.md @@ -65,6 +65,7 @@ The following table lists the configurable parameters of the Sysdig Registry Sca | config.registryUser | The username for registry authentication. | "" | | config.registryPassword | The password for registry authentication. | "" | | config.registryType | **required**
The registry Type. Supported types: artifactory, ecr, icr, acr, quay, harbor, gar, gcr, nexus, ocp and dockerv2. | "" | +| config.acr_workloadidentity | Use an Azure AD access token from the init container (IMDS) instead of `registryPassword` for ACR authentication. Applies only when `registryType` is `acr`. `registryUser` is still required and `registryPassword` is ignored. | false | | config.registryAccountId | The account ID. Applicable only for ICR registry type. | "" | | config.icrIamApi | The ICR IAM API. Applicable only for ICR registry type. | "" | | config.icrIamApiSkipTLS | Ignore TLS certificate for IAM API. Applicable only for ICR registry type. | false | diff --git a/charts/registry-scanner/values.yaml b/charts/registry-scanner/values.yaml index 57c5e79ed..324220a47 100644 --- a/charts/registry-scanner/values.yaml +++ b/charts/registry-scanner/values.yaml @@ -30,8 +30,8 @@ config: registryPassword: "" # **required**
The registry Type. Supported types: artifactory, ecr, icr, acr, quay, harbor, gar, gcr, nexus, ocp and dockerv2. registryType: "" - # Use Azure workload identity (AAD token) instead of username/password for ACR authentication. - # Requires registryType to be 'acr' and the pod to have azure.workload.identity annotations. + # Use an Azure AD access token from the init container (IMDS) instead of registryPassword for ACR authentication. + # Applies only when registryType is 'acr'. registryUser is still required; registryPassword is ignored. acr_workloadidentity: false # The account ID. Applicable only for ICR registry type. registryAccountId: "" From a1578ad4a8af943224b287c588e45b45fab15d57 Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 16 Jul 2026 10:58:17 -0400 Subject: [PATCH 3/9] build(chore): bump registry-scanner chart minor version --- charts/registry-scanner/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/registry-scanner/Chart.yaml b/charts/registry-scanner/Chart.yaml index 342a2beab..cccb3948e 100644 --- a/charts/registry-scanner/Chart.yaml +++ b/charts/registry-scanner/Chart.yaml @@ -7,4 +7,4 @@ maintainers: - name: sysdiglabs name: registry-scanner type: application -version: 1.11.1 +version: 1.12.0 From 64464e3cef72479f3776d2d55959c3dc4fb49c24 Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 16 Jul 2026 11:05:21 -0400 Subject: [PATCH 4/9] fix: linting when acr_workloadidentity is enabled --- charts/registry-scanner/templates/secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/registry-scanner/templates/secret.yaml b/charts/registry-scanner/templates/secret.yaml index 5abba14d6..3a0cbc21a 100644 --- a/charts/registry-scanner/templates/secret.yaml +++ b/charts/registry-scanner/templates/secret.yaml @@ -20,7 +20,7 @@ data: registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- else if eq .Values.config.registryType "ocp" }} registryUser: {{ "serviceaccount"| b64enc | quote }} - {{- else if not (and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity) }} + {{- else if not .Values.config.acr_workloadidentity }} registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- else }} registryUser: {{ required "A valid .Values.config.registryUser is required" .Values.config.registryUser | b64enc | quote }} From ccee90ee9c3422442e26137e56accf4359f491b2 Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 16 Jul 2026 11:26:08 -0400 Subject: [PATCH 5/9] feat(tests): add test coverage --- charts/registry-scanner/templates/secret.yaml | 2 +- charts/registry-scanner/tests/job_test.yaml | 74 +++++++++++++++++++ .../registry-scanner/tests/secret_test.yaml | 42 +++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 charts/registry-scanner/tests/secret_test.yaml diff --git a/charts/registry-scanner/templates/secret.yaml b/charts/registry-scanner/templates/secret.yaml index 3a0cbc21a..02710ec31 100644 --- a/charts/registry-scanner/templates/secret.yaml +++ b/charts/registry-scanner/templates/secret.yaml @@ -20,7 +20,7 @@ data: registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- else if eq .Values.config.registryType "ocp" }} registryUser: {{ "serviceaccount"| b64enc | quote }} - {{- else if not .Values.config.acr_workloadidentity }} + {{- else if not (and .Values.config.acr_workloadidentity (or (eq .Values.config.registryType "acr") (eq .Values.config.registryType ""))) }} registryPassword: {{ required "A valid .Values.config.registryPassword is required" .Values.config.registryPassword | b64enc | quote }} {{- else }} registryUser: {{ required "A valid .Values.config.registryUser is required" .Values.config.registryUser | b64enc | quote }} diff --git a/charts/registry-scanner/tests/job_test.yaml b/charts/registry-scanner/tests/job_test.yaml index 9eaf5a0d3..cb50ccca3 100644 --- a/charts/registry-scanner/tests/job_test.yaml +++ b/charts/registry-scanner/tests/job_test.yaml @@ -176,3 +176,77 @@ tests: secretKeyRef: name: RELEASE-NAME-registry-scanner key: aws_region + + - it: wires ACR workload identity token fetcher and password file env vars + set: + scanOnStart.enabled: true + config.registryType: "acr" + config.registryUser: "dummy" + config.acr_workloadidentity: true + asserts: + - contains: + path: spec.template.spec.initContainers + content: + name: aad-token-fetcher + - contains: + path: spec.template.spec.volumes + content: + name: aad-token + emptyDir: {} + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: aad-token + mountPath: /aad-token + - contains: + path: spec.template.spec.containers[0].env + content: + name: REGISTRYSCANNER_REGISTRY_PASSWORD + value: "" + - contains: + path: spec.template.spec.containers[0].env + content: + name: REGISTRYSCANNER_REGISTRY_PASSWORD_FILE + value: /aad-token/token + + - it: does not wire ACR workload identity token fetcher when flag is disabled + set: + scanOnStart.enabled: true + config.registryType: "acr" + config.registryUser: "dummy" + config.registryPassword: "dummy" + config.acr_workloadidentity: false + asserts: + - isNull: + path: spec.template.spec.initContainers + - notContains: + path: spec.template.spec.containers[0].env + content: + name: REGISTRYSCANNER_REGISTRY_PASSWORD_FILE + value: /aad-token/token + + - it: does not wire ACR workload identity token fetcher for non-ACR registries + set: + scanOnStart.enabled: true + config.registryType: "quay" + config.registryUser: "dummy" + config.registryPassword: "dummy" + config.acr_workloadidentity: true + asserts: + - isNull: + path: spec.template.spec.initContainers + - notContains: + path: spec.template.spec.volumes + content: + name: aad-token + emptyDir: {} + - notContains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: aad-token + mountPath: /aad-token + - notContains: + path: spec.template.spec.containers[0].env + content: + name: REGISTRYSCANNER_REGISTRY_PASSWORD_FILE + value: /aad-token/token diff --git a/charts/registry-scanner/tests/secret_test.yaml b/charts/registry-scanner/tests/secret_test.yaml new file mode 100644 index 000000000..21b00f9d5 --- /dev/null +++ b/charts/registry-scanner/tests/secret_test.yaml @@ -0,0 +1,42 @@ +suite: Registry Scanner - Secret +templates: + - templates/secret.yaml +tests: + - it: should set registryPassword for ACR when workload identity is disabled + set: + config.secureAPIToken: dummy + config.registryType: acr + config.registryPassword: dummy + config.acr_workloadidentity: false + asserts: + - equal: + path: data.registryPassword + value: ZHVtbXk= + - isNull: + path: data.registryUser + + - it: should set registryUser and omit registryPassword for ACR when workload identity is enabled + set: + config.secureAPIToken: dummy + config.registryType: acr + config.registryUser: dummy + config.acr_workloadidentity: true + asserts: + - equal: + path: data.registryUser + value: ZHVtbXk= + - isNull: + path: data.registryPassword + + - it: should still set registryPassword for non-ACR registries even when workload identity is enabled + set: + config.secureAPIToken: dummy + config.registryType: quay + config.registryPassword: dummy + config.acr_workloadidentity: true + asserts: + - equal: + path: data.registryPassword + value: ZHVtbXk= + - isNull: + path: data.registryUser From 55a418c7b7280fa03f1dde67f1a89efd6e6eaef1 Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 30 Jul 2026 11:15:54 -0400 Subject: [PATCH 6/9] fix: add workload identity label --- charts/registry-scanner/templates/_job.tpl | 59 ++++++++++++++++------ 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/charts/registry-scanner/templates/_job.tpl b/charts/registry-scanner/templates/_job.tpl index 03ea70811..b1c2b5743 100644 --- a/charts/registry-scanner/templates/_job.tpl +++ b/charts/registry-scanner/templates/_job.tpl @@ -9,6 +9,9 @@ labels: {{- include "registry-scanner.labels" . | nindent 12 }} {{- include "registry-scanner.customLabels" . | nindent 12 }} + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + azure.workload.identity/use: "true" + {{- end }} {{- with .Values.podAnnotations }} annotations: {{- toYaml . | nindent 12 }} @@ -30,28 +33,54 @@ - /bin/sh - -c - | - set -e - # Fetch AAD token from IMDS for ACR + # Obtain an ACR refresh token as the *federated* managed identity (the UAMI in the + # service account's azure.workload.identity/client-id annotation), NOT the node/kubelet + # identity. The azure-workload-identity webhook injects AZURE_CLIENT_ID / AZURE_TENANT_ID / + # AZURE_FEDERATED_TOKEN_FILE because the pod carries azure.workload.identity/use=true. REGISTRY_URL="{{ .Values.config.registryURL }}" - ENDPOINT="http://169.254.169.254/metadata/identity/oauth2/token?api-version=2017-09-01&resource=https://${REGISTRY_URL}" - + : "${AZURE_CLIENT_ID:?workload identity not injected (AZURE_CLIENT_ID unset) - check the SA azure.workload.identity/client-id annotation and the azure.workload.identity/use pod label}" + : "${AZURE_TENANT_ID:?workload identity not injected (AZURE_TENANT_ID unset)}" + : "${AZURE_FEDERATED_TOKEN_FILE:?workload identity not injected (AZURE_FEDERATED_TOKEN_FILE unset)}" + AUTHORITY_HOST="${AZURE_AUTHORITY_HOST:-https://login.microsoftonline.com/}" + + fetch_token() { + FED_TOKEN="$(cat "$AZURE_FEDERATED_TOKEN_FILE")" + # 1) Federated client-assertion exchange -> AAD access token for the ACR data plane. + AAD_TOKEN="$(curl -s -X POST \ + "${AUTHORITY_HOST}${AZURE_TENANT_ID}/oauth2/v2.0/token" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode "client_id=${AZURE_CLIENT_ID}" \ + --data-urlencode 'grant_type=client_credentials' \ + --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ + --data-urlencode "client_assertion=${FED_TOKEN}" \ + --data-urlencode 'scope=https://containerregistry.azure.net/.default' \ + | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)" + [ -n "$AAD_TOKEN" ] || return 1 + # 2) Exchange the AAD token for an ACR refresh token (the docker password used with the + # null-GUID username the chart sets as registryUser). + ACR_TOKEN="$(curl -s -X POST \ + "https://${REGISTRY_URL}/oauth2/exchange" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'grant_type=access_token' \ + --data-urlencode "service=${REGISTRY_URL}" \ + --data-urlencode "tenant=${AZURE_TENANT_ID}" \ + --data-urlencode "access_token=${AAD_TOKEN}" \ + | grep -o '"refresh_token":"[^"]*' | cut -d'"' -f4)" + [ -n "$ACR_TOKEN" ] || return 1 + printf '%s' "$ACR_TOKEN" > /aad-token/token + } + MAX_RETRIES=5 RETRY_COUNT=0 while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - if TOKEN=$(curl -s -H "Metadata:true" "$ENDPOINT" 2>/dev/null | grep -o '"access_token":"[^"]*' | cut -d'"' -f4); then - if [ -n "$TOKEN" ]; then - echo "$TOKEN" > /aad-token/token - echo "AAD token fetched successfully" - exit 0 - fi + if fetch_token; then + echo "ACR refresh token obtained via workload identity" + exit 0 fi RETRY_COUNT=$((RETRY_COUNT + 1)) - if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then - echo "Retrying IMDS token fetch ($RETRY_COUNT/$MAX_RETRIES)..." - sleep 2 - fi + [ $RETRY_COUNT -lt $MAX_RETRIES ] && { echo "Retrying ACR token fetch ($RETRY_COUNT/$MAX_RETRIES)..."; sleep 2; } done - echo "Failed to fetch AAD token after $MAX_RETRIES attempts" + echo "Failed to obtain ACR token via workload identity after $MAX_RETRIES attempts" >&2 exit 1 volumeMounts: - name: aad-token From 6f19c46d14103f18951e52a5e7bc2fc6b2ea72eb Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 30 Jul 2026 11:36:18 -0400 Subject: [PATCH 7/9] fix: initcontianer repo update for quay.io --- charts/registry-scanner/values.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/charts/registry-scanner/values.yaml b/charts/registry-scanner/values.yaml index 324220a47..246099600 100644 --- a/charts/registry-scanner/values.yaml +++ b/charts/registry-scanner/values.yaml @@ -30,8 +30,11 @@ config: registryPassword: "" # **required**
The registry Type. Supported types: artifactory, ecr, icr, acr, quay, harbor, gar, gcr, nexus, ocp and dockerv2. registryType: "" - # Use an Azure AD access token from the init container (IMDS) instead of registryPassword for ACR authentication. - # Applies only when registryType is 'acr'. registryUser is still required; registryPassword is ignored. + # Authenticate to ACR as the federated managed identity (Azure Workload Identity) via an init + # container, instead of registryPassword. The init container exchanges the projected federated + # token for an ACR refresh token. Requires the service account to be annotated with + # azure.workload.identity/client-id; the chart adds the azure.workload.identity/use pod label. + # Applies only when registryType is 'acr'. registryUser is still required (null GUID); registryPassword is ignored. acr_workloadidentity: false # The account ID. Applicable only for ICR registry type. registryAccountId: "" @@ -185,8 +188,8 @@ image: fips: false # Init container image registry for AAD token fetcher (when registryType is acr). Defaults to the main image registry. initContainerRegistry: "" - # Init container image repository for AAD token fetcher. Defaults to library/curl on the main registry. - initContainerRepository: "library/curl" + # Init container image repository for AAD token fetcher. Defaults to curel/curl on the main registry. + initContainerRepository: "curl/curl" # Init container image tag. Defaults to 7.85.0 initContainerTag: "7.85.0" # Init container pull policy. Defaults to the main pullPolicy. From a533024e156128c37ca5089ee78163e4e025e27d Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 30 Jul 2026 11:38:44 -0400 Subject: [PATCH 8/9] build(deps); update curl initContainerTag to 8.21.0 --- charts/registry-scanner/values.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/registry-scanner/values.yaml b/charts/registry-scanner/values.yaml index 246099600..b46b30d99 100644 --- a/charts/registry-scanner/values.yaml +++ b/charts/registry-scanner/values.yaml @@ -190,8 +190,8 @@ image: initContainerRegistry: "" # Init container image repository for AAD token fetcher. Defaults to curel/curl on the main registry. initContainerRepository: "curl/curl" - # Init container image tag. Defaults to 7.85.0 - initContainerTag: "7.85.0" + # Init container image tag. Defaults to 8.21.0 + initContainerTag: "8.21.0" # Init container pull policy. Defaults to the main pullPolicy. initContainerPullPolicy: "" From 549a97159a913137319df28002f70e86af10cf08 Mon Sep 17 00:00:00 2001 From: Layer8Err Date: Thu, 30 Jul 2026 13:21:04 -0400 Subject: [PATCH 9/9] fix: handle env vars --- charts/registry-scanner/templates/_job.tpl | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/charts/registry-scanner/templates/_job.tpl b/charts/registry-scanner/templates/_job.tpl index b1c2b5743..3e0adafb4 100644 --- a/charts/registry-scanner/templates/_job.tpl +++ b/charts/registry-scanner/templates/_job.tpl @@ -45,7 +45,9 @@ fetch_token() { FED_TOKEN="$(cat "$AZURE_FEDERATED_TOKEN_FILE")" - # 1) Federated client-assertion exchange -> AAD access token for the ACR data plane. + # 1) Federated client-assertion exchange -> AAD access token. ACR with + # azureAdAuthenticationAsArmPolicy enabled expects the ARM audience; a token for + # the ACR-specific audience yields a refresh token that lacks registry:catalog:*. AAD_TOKEN="$(curl -s -X POST \ "${AUTHORITY_HOST}${AZURE_TENANT_ID}/oauth2/v2.0/token" \ -H 'Content-Type: application/x-www-form-urlencoded' \ @@ -53,7 +55,7 @@ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ --data-urlencode "client_assertion=${FED_TOKEN}" \ - --data-urlencode 'scope=https://containerregistry.azure.net/.default' \ + --data-urlencode 'scope=https://management.azure.com/.default' \ | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)" [ -n "$AAD_TOKEN" ] || return 1 # 2) Exchange the AAD token for an ACR refresh token (the docker password used with the @@ -86,15 +88,30 @@ - name: aad-token mountPath: /aad-token securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65534 + runAsGroup: 65534 + seccompProfile: + type: RuntimeDefault {{- end }} containers: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 14 }} image: {{ include "registry-scanner.image" . }} + {{- if and (eq .Values.config.registryType "acr") .Values.config.acr_workloadidentity }} + # The scanner binary ignores REGISTRYSCANNER_REGISTRY_PASSWORD_FILE; load the WIF-minted ACR + # token that the init container wrote into the password env, then exec the scanner. + command: ["/bin/sh", "-c", "export REGISTRYSCANNER_REGISTRY_PASSWORD=\"$(cat /aad-token/token)\"; exec /registry-scanner \"$@\"", "registry-scanner"] + args: ["--scan_runner=new-vm-scanner-k8s-job"] + {{- else }} args: [ "--scan_runner=new-vm-scanner-k8s-job"] + {{- end }} imagePullPolicy: {{ .Values.image.pullPolicy }} resources: {{- toYaml .Values.resources | nindent 14 }}