Azure Workload Identity Federation
Overview
Section titled “Overview”This guide configures Azure Key Vault as a secret provider using Microsoft Entra Workload Identity Federation: CrewAI Platform mints short-lived OIDC tokens, exchanges them for an Entra access token via the Microsoft identity platform, and reads your secrets — without any client secret being stored anywhere.
How it works at runtime
Section titled “How it works at runtime”- The deployment worker requests a fresh OIDC JWT from CrewAI Platform.
- The worker presents the JWT to Microsoft Entra at
https://login.microsoftonline.com/<tenant>/oauth2/v2.0/tokenas aclient_assertion(urn:ietf:params:oauth:client-assertion-type:jwt-bearer), referencing the App Registration whose Federated Identity Credential matches the JWT’s issuer + subject. - Entra validates the JWT against your platform’s OIDC discovery document and JWKS, then returns a short-lived access token scoped to
https://vault.azure.net/.default. - The worker calls Azure Key Vault to read the secret.
- The fetched value is injected as the environment variable’s value for that automation kickoff.
OIDC subject tokens are cached for ~1 hour to avoid re-issuing on every kickoff. Secret values are fetched fresh on every kickoff regardless of OIDC cache state, which is what makes this path rotation-aware.
Prerequisites
Section titled “Prerequisites”Step 1 — Find Your CrewAI Platform OIDC Issuer URL
Section titled “Step 1 — Find Your CrewAI Platform OIDC Issuer URL”Your CrewAI Platform installation publishes an OpenID Connect discovery document at https://<your-platform-host>/.well-known/openid-configuration. The issuer field there is the URL Microsoft Entra will register as a trusted federation issuer.
Open the URL in a browser:
https://<your-platform-host>/.well-known/openid-configurationYou should see JSON containing:
{ "issuer": "https://<your-platform-host>", "jwks_uri": "https://<your-platform-host>/oauth2/jwks", ...}Note the exact value of issuer — you’ll use it in Step 3.
Step 2 — Create an App Registration
Section titled “Step 2 — Create an App Registration”In the Microsoft Entra portal, navigate to App registrations and click New registration.
- Name:
crewai-secrets-reader - Supported account types:
Accounts in this organizational directory only (Single tenant). - Leave Redirect URI blank.
Click Register. Note the Application (client) ID and Directory (tenant) ID on the App’s overview blade — you’ll use them in Step 6.
Step 3 — Add a Federated Identity Credential
Section titled “Step 3 — Add a Federated Identity Credential”The Federated Identity Credential tells Microsoft Entra: trust JWTs minted by this issuer, with this subject, when they’re presented as a client assertion for this App Registration.
On the App Registration, navigate to Certificates & secrets → Federated credentials → Add credential.
- Federated credential scenario:
Other issuer. - Issuer: the CrewAI Platform issuer URL from Step 1, e.g.
https://<your-platform-host>. - Subject identifier:
organization:<YOUR_CREWAI_ORG_UUID>— exactly the value of the JWT’ssubclaim. Find your org UUID in CrewAI Platform’s organization settings. This scopes federation to a specific CrewAI organization — only tokens minted for that org’s automations are accepted. - Name: any descriptive label, e.g.
crewai-org-prod. - Audience:
api://AzureADTokenExchange. This is the fixed audience Microsoft Entra requires for federated credentials and is what CrewAI Platform sets in the JWT’saudclaim.
Click Add.
For full details, see the Microsoft documentation: Configure a federated identity credential on an app.
Step 4 — Grant the App Registration Access to Key Vault
Section titled “Step 4 — Grant the App Registration Access to Key Vault”Grant the App Registration Key Vault Secrets User on the target vault — the same role you’d use for the static-credentials path. Use either vault-wide (simpler) or per-secret (least privilege).
az role assignment create \ --assignee <APPLICATION_CLIENT_ID> \ --role "Key Vault Secrets User" \ --scope $(az keyvault show --name <VAULT_NAME> --query id -o tsv)Vault-wide scope grants the secrets/list permission that the Secret Name autocomplete in CrewAI Platform’s env-var form depends on. Choose this tab if you want autocomplete to work.
az role assignment create \ --assignee <APPLICATION_CLIENT_ID> \ --role "Key Vault Secrets User" \ --scope $(az keyvault secret show --vault-name <VAULT_NAME> --name <SECRET_NAME> --query id -o tsv)Per-secret bindings disable the Secret Name autocomplete in CrewAI Platform’s env-var form (autocomplete requires secrets/list, which is vault-scoped only). Type the full secret name instead.
For a vault-wide assignment:
- Open your Key Vault in the Azure portal.
- Click Access control (IAM) → Add → Add role assignment.
- Select role Key Vault Secrets User → Next.
- Click Select members, search for the App Registration
crewai-secrets-reader, click Select. - Click Review + assign.
For a per-secret assignment, use the same flow but start from Objects → Secrets → select the secret → its own Access control (IAM) panel. Per-secret bindings disable autocomplete (see the Per-secret tab above).
Step 5 — Create at Least One Secret in Key Vault
Section titled “Step 5 — Create at Least One Secret in Key Vault”If you don’t already have a secret to test against, create one via the Azure CLI:
az keyvault secret set \ --vault-name <VAULT_NAME> \ --name openai-api-key \ --value "sk-your-actual-key"Or via the Azure portal:
- Open your Key Vault and navigate to Objects → Secrets.
- Click Generate/Import.
- Upload options:
Manual. Name: the secret name (e.g.openai-api-key). Secret value: paste the value. - Click Create.
Step 6 — Add a Workload Identity Configuration in CrewAI Platform
Section titled “Step 6 — Add a Workload Identity Configuration in CrewAI Platform”In CrewAI Platform, navigate to Settings → Workload Identity and click Add Workload Identity Config.
Fill the form:
- Name: A descriptive name, e.g.
azure-prod. - Cloud Provider:
Azure. - Tenant ID: your Microsoft Entra Directory (tenant) ID from Step 2.
- Client ID: your App Registration’s Application (client) ID from Step 2.
- (Optional) Check Set as default for Azure if you’d like this to be the default WI config selected when creating an Azure-backed secret credential.
The Audience is fixed at api://AzureADTokenExchange — Microsoft Entra requires this exact audience for federated credentials, so no Audience field is shown on the form.
Click Create.
Step 7 — Add a Secret Provider Credential Bound to the WI Config
Section titled “Step 7 — Add a Secret Provider Credential Bound to the WI Config”Navigate to Settings → Secret Provider Credentials and click Add Credential.
Fill the form:
- Name: A descriptive name, e.g.
azure-prod-wi. - Provider:
Azure Key Vault. - Authentication Method:
Workload Identity. - Workload Identity Configuration: select the config you created in Step 6.
- Key Vault URL: the vault’s DNS hostname, e.g.
https://my-vault.vault.azure.net. - (Optional) Check Set as default credential for this provider.
The form will only ask for Key Vault URL under Workload Identity — the static-credential fields (Tenant ID, Client ID, Client Secret) are intentionally hidden because they don’t apply to this path; tenant + client come from the linked WI config.
Click Create.
Step 8 — Test the Connection
Section titled “Step 8 — Test the Connection”After saving the credential, click Test Connection. For workload-identity credentials this verifies the OIDC handshake: CrewAI Platform mints a JWT, presents it to Microsoft Entra as a federated client_assertion, and confirms Entra returns a vault-scoped access token. A green result means the federation binding is healthy.
A successful Test Connection proves the Federated Identity Credential’s issuer, subject, and audience all match, and that the App Registration is reachable. It does not prove per-secret Key Vault RBAC is correct — getSecret against a specific secret is exercised separately when an environment variable resolves at kickoff. See Troubleshooting for handshake failure modes.
Step 9 — Reference the Secret in an Environment Variable
Section titled “Step 9 — Reference the Secret in an Environment Variable”Reference the secret on an automation, exactly as you would for any other Secrets Manager-backed env var. See Using the Secrets Manager for the form fields and behavior.
Step 10 — Verify Rotation
Section titled “Step 10 — Verify Rotation”After the deployment is running, rotate the secret in Key Vault:
az keyvault secret set \ --vault-name <VAULT_NAME> \ --name openai-api-key \ --value "rotated value"Trigger a new automation kickoff. The kickoff’s environment will see "rotated value" — no re-deploy, no worker restart, no TTL wait.
To confirm in worker logs, look for:
Workload identity config '<id>' (azure): N secret(s) resolvedThis line appears for every kickoff and indicates a fresh getSecret call against Azure Key Vault.
For an end-to-end fingerprint-based verification, see Verify Rotation End-to-End.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause |
|---|---|
| Test Connection fails with a handshake error | The federated client_assertion was rejected by Microsoft Entra. Verify the Federated Identity Credential’s Issuer matches the platform’s issuer value exactly, Subject is organization:<your-org-uuid> (matching the JWT’s sub claim), Audience is api://AzureADTokenExchange, and the platform’s OIDC discovery URL is reachable from Entra over the public internet. |
AADSTS70021: No matching federated identity record found for presented assertion | The Federated Identity Credential’s Issuer + Subject + Audience don’t all match the JWT exactly. Re-check Step 3: subject must be organization:<your-org-uuid> (matching the JWT’s sub claim), audience must be api://AzureADTokenExchange. |
AADSTS700024: Client assertion is not within its valid time range | The CrewAI Platform host’s clock is significantly skewed from real time. Check NTP on the host. |
AADSTS50013: Assertion failed signature validation | Microsoft Entra couldn’t verify the JWT’s signature. Confirm https://<your-platform-host>/oauth2/jwks is reachable from the public internet and serves a valid JWKS. |
Secret Name autocomplete shows Forbidden — does not have permission to perform action 'Microsoft.KeyVault/vaults/secrets/.../list' | The App Registration’s Key Vault Secrets User role is scoped to a single secret. Grant the role at the vault scope so the list data-plane action is allowed. See Step 4. |
| Kickoff fails to resolve a secret even though Test Connection passes | The WI binding is healthy, but per-secret Key Vault RBAC is missing on the failing secret. Audit Key Vault Secrets User on that specific secret (or extend the role assignment to the vault scope). |
Forbidden — request was not authorized (vault using legacy access policies) | The vault hasn’t been switched to Azure RBAC. Under the vault’s Access configuration, set permission model to Azure role-based access control and re-grant the role from Step 4. |
azure_vault_url is required for Azure secret resolution (worker logs) | The Secret Provider Credential is missing Key Vault URL. Re-check Step 7. |
| Rotated value isn’t picked up on the next kickoff | Confirm the env var on the automation is referencing a Workload Identity-backed credential (not a static-keys credential). The static path bakes values into the deploy image. |
Reference Links
Section titled “Reference Links”- Microsoft: Microsoft Entra Workload Identity Federation overview
- Microsoft: Configure a federated identity credential on an app
- Microsoft: Azure Key Vault RBAC guide
Next Steps
Section titled “Next Steps”- Use secrets in environment variables and manage permissions
- For multi-cloud, the AWS-equivalent setup is at AWS Workload Identity (OIDC Federation) and the GCP-equivalent at GCP Workload Identity Federation.
Screenshot Reference
Section titled “Screenshot Reference”The placeholders above map to:
01-register-app.png— Azure portal “Register an application” form filled withcrewai-secrets-reader.02-add-federated-credential.png— App Registration → Certificates & secrets → Federated credentials → Add credential, with Other issuer, the platform issuer URL, subjectorganization:<uuid>, audienceapi://AzureADTokenExchange.03-grant-vault-rbac.png— Key Vault → Access control (IAM) → Add role assignment, with Key Vault Secrets User and the App Registration selected.04-per-secret-rbac.png— Same form but at a single secret’s IAM scope (alternative least-privilege path).05-amp-add-wi-config-azure.png— CrewAI Platform “Add Workload Identity Config” form with Cloud Provider = Azure, Tenant ID, Client ID populated.06-amp-wi-list-with-azure.png— Workload Identity list page after creation, showing rows for AWS, GCP, and the new Azure config.07-amp-add-credential-azure-wi.png— “Add Secret Provider Credential” form with Provider = Azure Key Vault, Auth = Workload Identity, the WI config picked, and Key Vault URL populated.