Support Azure Workload Identity (WIF) in image stream registry env vars#442
Support Azure Workload Identity (WIF) in image stream registry env vars#442kaovilai wants to merge 1 commit into
Conversation
Fixes openshift#439 (OADP-6675) getAzureRegistryEnvVars() always referenced the oadp-<bsl>-azure-registry-secret for REGISTRY_STORAGE_AZURE_ACCOUNTKEY and the SPN env vars. On Azure WIF/STS clusters the OADP operator never creates that secret (there are no long-lived credentials to extract), so image stream backup failed with: secrets "oadp-<bsl>-azure-registry-secret" not found Detect WIF by reading the BSL credential secret (bsl.Spec.Credential, or the OADP default cloud-credentials-azure/cloud) and checking that it contains no long-lived credentials (AZURE_STORAGE_ACCOUNT_ACCESS_KEY, AZURE_CLIENT_SECRET) and does contain AZURE_FEDERATED_TOKEN_FILE, or AZURE_CLIENT_ID plus AZURE_TENANT_ID (the format written by the operator's stsflow.CreateOrUpdateSTSAzureSecret). If the secret cannot be read, fall back to the previous long-lived behavior. In WIF mode only REGISTRY_STORAGE, REGISTRY_STORAGE_AZURE_CONTAINER and REGISTRY_STORAGE_AZURE_ACCOUNTNAME are set. With no accountkey and no credentials.type=client_secret parameter, newAzureClient() in the openshift/docker-distribution v3 azure storage driver falls through to azidentity.NewDefaultAzureCredential, which authenticates via WorkloadIdentityCredential using AZURE_CLIENT_ID, AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE from the Velero pod environment. The registry runs in-process (udistribution) inside the Velero pod, so the pod environment is the process environment azidentity reads. Changes required in other repos: none for OADP 1.5+. - openshift/oadp-operator (oadp-1.5 and oadp-dev already implement this): ReconcileAzureWorkloadIdentitySecret creates the azure-workload-identity-env secret (AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/openshift/serviceaccount/token) and injects it into the Velero deployment via envFrom; the bound-sa-token projected volume is always mounted at /var/run/secrets/openshift/serviceaccount. Operator versions without that wiring (OADP <= 1.4) would additionally need it for this fix to work. - openshift/docker-distribution (v3, pinned via go.mod replace): no change; the azure driver DefaultAzureCredential fallthrough already exists. - migtools/udistribution: no change; it only consumes REGISTRY_* env strings for registry config, while azidentity reads AZURE_* from the process environment. Credential type limitations: - WIF requires the BSL to reference the STS-flow credential secret (e.g. cloud-credentials-azure/azurekey). If the BSL credential cannot be read, the long-lived path is assumed. - Storage account key auth is unchanged (REGISTRY_STORAGE_AZURE_ACCOUNTKEY from the registry secret). - SPN (client secret) BSLs keep the existing REGISTRY_STORAGE_AZURE_SPN_* wiring, but those env var names parse into storage.azure.spn.client.id etc., which do not map to the distribution/v3 azure driver's credentials.{type,clientid,tenantid,secret} parameters, so registry SPN auth was and remains non-functional; account key and WIF are the working auth modes for the in-process registry. - The WIF identity must be authorized to generate user delegation keys on the storage account (e.g. Storage Blob Data Contributor), since the token-credential path signs blob URLs with user delegation SAS. Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
|
Caution Review failedAn error occurred during the review process. Please try again later. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: kaovilai The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/hold for testing in far future |
|
@kaovilai: all tests passed! Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
Note
Responses generated with Claude
Fixes #439 (linked Jira: OADP-6675)
Problem
getAzureRegistryEnvVars()always referencedoadp-<bsl>-azure-registry-secretforREGISTRY_STORAGE_AZURE_ACCOUNTKEYand the SPN env vars. On Azure Workload Identity (WIF/STS) clusters the OADP operator never creates that secret (no long-lived credentials to extract), so image stream backup failed with:Fix
isAzureWorkloadIdentity): read the BSL credential secret (bsl.spec.credential, or OADP defaultcloud-credentials-azure/cloud). WIF when it contains no long-lived credentials (AZURE_STORAGE_ACCOUNT_ACCESS_KEY,AZURE_CLIENT_SECRET) and hasAZURE_FEDERATED_TOKEN_FILE, orAZURE_CLIENT_ID+AZURE_TENANT_ID(format written by the operator'sstsflow.CreateOrUpdateSTSAzureSecret). If the secret cannot be read, fall back to the previous long-lived behavior.REGISTRY_STORAGE=azure,REGISTRY_STORAGE_AZURE_CONTAINER,REGISTRY_STORAGE_AZURE_ACCOUNTNAME. With noaccountkeyand nocredentials.type=client_secretparameter,newAzureClient()in the openshift/docker-distribution v3 azure driver falls through toazidentity.NewDefaultAzureCredential, which authenticates viaWorkloadIdentityCredentialusingAZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_FEDERATED_TOKEN_FILEfrom the Velero pod environment. The registry runs in-process (udistribution) inside the Velero pod, so the pod environment is exactly the process environment azidentity reads.getBslSecretPathinto a sharedgetBslSecretKeySelector; addedparseAzureCredentialsConfigenv-file parser.Changes required in other repos
None for OADP 1.5+:
ReconcileAzureWorkloadIdentitySecretcreatesazure-workload-identity-envsecret (AZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/openshift/serviceaccount/token) and injects it into the Velero deployment viaenvFrom;bound-sa-tokenprojected volume always mounted at/var/run/secrets/openshift/serviceaccount. OADP ≤ 1.4 operator lacks this wiring and would need it for this fix to work there.DefaultAzureCredentialfallthrough already presentREGISTRY_*env strings for registry config, azidentity readsAZURE_*from process envCredential type limitations
cloud-credentials-azure/azurekey). Unreadable credential secret → long-lived path assumed.REGISTRY_STORAGE_AZURE_SPN_*wiring, but those env var names parse intostorage.azure.spn.client.idetc., which do not map to the distribution/v3 azure driver'scredentials.{type,clientid,tenantid,secret}parameters — registry SPN auth was and remains non-functional. Account key and WIF are the working auth modes for the in-process registry.Testing
make test— all packages pass.Test_getAzureRegistryEnvVars_WorkloadIdentity(envtest): WIF secret → 3 env vars only; storage-account-key secret, SPN secret, missing secret → unchanged long-lived env vars.Test_parseAzureCredentialsConfigunit tests (operator azurekey format, quotes/CRLF/comments/sections, empty data).🤖 Generated with Claude Code