mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-04 14:39:23 +00:00
276 lines
17 KiB
Plaintext
276 lines
17 KiB
Plaintext
---
|
|
title: Azure Workload Identity Federation
|
|
description: Configure Azure Key Vault via Microsoft Entra Workload Identity Federation for rotation-aware, credential-free secret access
|
|
sidebarTitle: With Workload Identity
|
|
icon: "id-badge"
|
|
---
|
|
|
|
## 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.
|
|
|
|
<Note>
|
|
**Why this path:** secrets are resolved at automation execution time, so **rotated values propagate to the next kickoff with no re-deploy**. If you only need static credentials, see the simpler [Azure Key Vault — client secret](/en/enterprise/features/secrets-manager/azure) guide.
|
|
</Note>
|
|
|
|
### How it works at runtime
|
|
|
|
1. The deployment worker requests a fresh OIDC JWT from CrewAI Platform.
|
|
2. The worker presents the JWT to Microsoft Entra at `https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token` as a `client_assertion` (`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`), referencing the App Registration whose **Federated Identity Credential** matches the JWT's issuer + subject.
|
|
3. 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`.
|
|
4. The worker calls Azure Key Vault to read the secret.
|
|
5. 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
|
|
|
|
<Note>
|
|
Before starting, make sure you have:
|
|
|
|
- The automation pod image must include CrewAI runtime version `1.14.5` or later.
|
|
- An Azure subscription and a Microsoft Entra tenant you can manage.
|
|
- Permission in the tenant to create App Registrations and add Federated Identity Credentials.
|
|
- A Key Vault using **Azure RBAC** for authorization (not the legacy access-policy model).
|
|
- A CrewAI Platform organization where your user has the `workload_identity_configs: manage` and `secret_providers: manage` permissions. See [Permissions (RBAC)](/en/enterprise/features/secrets-manager/usage#permissions-rbac).
|
|
- **Your CrewAI Platform installation must be reachable from Microsoft Entra over HTTPS** so that Entra can fetch the OIDC discovery document and JWKS during token validation. Confirm with your platform administrator that the host is internet-accessible.
|
|
</Note>
|
|
|
|
## 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-configuration
|
|
```
|
|
|
|
You should see JSON containing:
|
|
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
<Tip>
|
|
If the URL returns 404 or 503, contact your platform administrator. The OIDC issuer requires a private signing key to be configured at install time. See the platform's installation guide for the `OIDC_PRIVATE_KEY` and `OIDC_ISSUER` configuration.
|
|
</Tip>
|
|
|
|
## Step 2 — Create an App Registration
|
|
|
|
In the [Microsoft Entra portal](https://entra.microsoft.com), 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.
|
|
|
|
{/* SCREENSHOT: Azure portal "Register an application" form with name "crewai-secrets-reader" → /images/secrets-manager/azure-wi/01-register-app.png */}
|
|
|
|
## 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's `sub` claim. 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's `aud` claim.
|
|
|
|
Click **Add**.
|
|
|
|
<Tip>
|
|
**Per-org isolation.** The subject identifier (`organization:<UUID>`) restricts the federated credential to a specific CrewAI organization's tokens. If multiple CrewAI organizations should share one App Registration, add one Federated Identity Credential per organization (each with the org's UUID).
|
|
</Tip>
|
|
|
|
For full details, see the Microsoft documentation: [Configure a federated identity credential on an app](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust).
|
|
|
|
{/* SCREENSHOT: "Add credential" panel with scenario = "Other issuer", issuer URL, subject "organization:<uuid>", audience "api://AzureADTokenExchange" → /images/secrets-manager/azure-wi/02-add-federated-credential.png */}
|
|
|
|
## 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).
|
|
|
|
<Tabs>
|
|
<Tab title="Vault-wide (simpler)">
|
|
```bash
|
|
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.
|
|
|
|
{/* SCREENSHOT: Key Vault "Add role assignment" panel with "Key Vault Secrets User" and the App Registration selected → /images/secrets-manager/azure-wi/03-grant-vault-rbac.png */}
|
|
</Tab>
|
|
|
|
<Tab title="Per-secret (least privilege)">
|
|
```bash
|
|
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.
|
|
|
|
{/* SCREENSHOT: Per-secret IAM panel with the App Registration assigned **Key Vault Secrets User** at the secret resource scope → /images/secrets-manager/azure-wi/04-per-secret-rbac.png */}
|
|
</Tab>
|
|
|
|
<Tab title="Portal (UI)">
|
|
For a **vault-wide** assignment:
|
|
|
|
1. Open your Key Vault in the Azure portal.
|
|
2. Click **Access control (IAM)** → **Add** → **Add role assignment**.
|
|
3. Select role **Key Vault Secrets User** → **Next**.
|
|
4. Click **Select members**, search for the App Registration `crewai-secrets-reader`, click **Select**.
|
|
5. 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).
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
## 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:
|
|
|
|
```bash
|
|
az keyvault secret set \
|
|
--vault-name <VAULT_NAME> \
|
|
--name openai-api-key \
|
|
--value "sk-your-actual-key"
|
|
```
|
|
|
|
Or via the Azure portal:
|
|
|
|
1. Open your Key Vault and navigate to **Objects** → **Secrets**.
|
|
2. Click **Generate/Import**.
|
|
3. **Upload options:** `Manual`. **Name:** the secret name (e.g. `openai-api-key`). **Secret value:** paste the value.
|
|
4. Click **Create**.
|
|
|
|
<Note>
|
|
**Secret name conventions.** Azure Key Vault secret names cannot contain underscores. CrewAI Platform automatically converts underscores to hyphens when calling Azure (e.g., `db_password` is sent as `db-password`), so you can keep underscore-style env-var names — but the underlying secret in Key Vault must use hyphens.
|
|
</Note>
|
|
|
|
## 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**.
|
|
|
|
{/* SCREENSHOT: "Add Workload Identity Config" form with Azure, tenant ID, client ID populated → /images/secrets-manager/azure-wi/05-amp-add-wi-config-azure.png */}
|
|
{/* SCREENSHOT: Workload Identity list showing AWS, GCP, and Azure rows → /images/secrets-manager/azure-wi/06-amp-wi-list-with-azure.png */}
|
|
|
|
## 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**.
|
|
|
|
<Tip>
|
|
**One App Registration, many vaults.** The Key Vault URL lives on the credential, not the WI config. So one App Registration (and one WI config) can serve multiple Key Vaults — just create one Secret Provider Credential per vault, all linked to the same WI config.
|
|
</Tip>
|
|
|
|
{/* SCREENSHOT: "Add Secret Provider Credential" form with Azure + Workload Identity + WI config dropdown + vault URL → /images/secrets-manager/azure-wi/07-amp-add-credential-azure-wi.png */}
|
|
|
|
## 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](#troubleshooting) for handshake failure modes.
|
|
|
|
## 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](/en/enterprise/features/secrets-manager/usage#referencing-secrets-in-environment-variables) for the form fields and behavior.
|
|
|
|
## Step 10 — Verify Rotation
|
|
|
|
After the deployment is running, rotate the secret in Key Vault:
|
|
|
|
```bash
|
|
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) resolved
|
|
```
|
|
|
|
This 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](/en/enterprise/features/secrets-manager/verify-rotation).
|
|
|
|
## 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
|
|
|
|
- Microsoft: [Microsoft Entra Workload Identity Federation overview](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation)
|
|
- Microsoft: [Configure a federated identity credential on an app](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust)
|
|
- Microsoft: [Azure Key Vault RBAC guide](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide)
|
|
|
|
## Next Steps
|
|
|
|
- [Use secrets in environment variables and manage permissions](/en/enterprise/features/secrets-manager/usage)
|
|
- For multi-cloud, the AWS-equivalent setup is at [AWS Workload Identity (OIDC Federation)](/en/enterprise/features/secrets-manager/aws-workload-identity) and the GCP-equivalent at [GCP Workload Identity Federation](/en/enterprise/features/secrets-manager/gcp-workload-identity).
|
|
|
|
## Screenshot Reference
|
|
|
|
The placeholders above map to:
|
|
|
|
- `01-register-app.png` — Azure portal "Register an application" form filled with `crewai-secrets-reader`.
|
|
- `02-add-federated-credential.png` — App Registration → Certificates & secrets → Federated credentials → Add credential, with **Other issuer**, the platform issuer URL, subject `organization:<uuid>`, audience `api://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.
|