跳转到内容

Azure Workload Identity Federation

本指南通过 Microsoft Entra Workload Identity Federation 配置 Azure Key Vault 作为密钥 provider:CrewAI Platform 会生成短期 OIDC tokens,通过 Microsoft identity platform 将其换成 Entra access token,然后读取你的密钥 - 全程不会存放任何 client secret。

  1. 部署 worker 从 CrewAI Platform 请求一个新的 OIDC JWT。
  2. worker 将 JWT 作为 client_assertionurn:ietf:params:oauth:client-assertion-type:jwt-bearer)提交给 Microsoft Entra 的 https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token,引用其 Federated Identity Credential 与 JWT 的 issuer + subject 匹配的 App Registration。
  3. Entra 根据你平台的 OIDC discovery document 和 JWKS 验证 JWT,然后返回一个 scope 为 https://vault.azure.net/.default 的短期 access token。
  4. worker 调用 Azure Key Vault 读取 secret。
  5. 获取到的值会在本次 automation kickoff 中被注入为环境变量值。

OIDC subject tokens 会缓存大约 1 小时,以避免每次 kickoff 都重新签发。无论 OIDC 缓存状态如何,secret values 都会在每次 kickoff 时刷新获取,这也是这条路径具备 rotation awareness 的原因。

第 1 步 - 找到 CrewAI Platform 的 OIDC Issuer URL

Section titled “第 1 步 - 找到 CrewAI Platform 的 OIDC Issuer URL”

你的 CrewAI Platform 安装会在 https://<your-platform-host>/.well-known/openid-configuration 发布一个 OpenID Connect discovery document。该文档中的 issuer 字段就是 Microsoft Entra 会注册为受信任 federation issuer 的 URL。

在浏览器中打开这个 URL:

https://<your-platform-host>/.well-known/openid-configuration

你应该会看到 JSON,包含:

{
"issuer": "https://<your-platform-host>",
"jwks_uri": "https://<your-platform-host>/oauth2/jwks",
...
}

记下 issuer 的准确值 - 第 3 步会用到它。

Microsoft Entra portal 中,进入 App registrations 并点击 New registration

  • Name: crewai-secrets-reader
  • Supported account types: Accounts in this organizational directory only (Single tenant)
  • 保留 Redirect URI 为空。

点击 Register。记下 App overview blade 上的 Application (client) IDDirectory (tenant) ID - 第 6 步会用到它们。

第 3 步 - 添加 Federated Identity Credential

Section titled “第 3 步 - 添加 Federated Identity Credential”

Federated Identity Credential 会告诉 Microsoft Entra:信任这个 issuer 签发的 JWT,只要 subject 也匹配,并且它们被当作这个 App Registration 的 client assertion 提交。

在 App Registration 上,进入 Certificates & secretsFederated credentialsAdd credential

  • Federated credential scenario: Other issuer
  • Issuer: 第 1 步中的 CrewAI Platform issuer URL,例如 https://<your-platform-host>
  • Subject identifier: organization:<YOUR_CREWAI_ORG_UUID> - 必须与 JWT 的 sub claim 完全一致。请在 CrewAI Platform 的组织设置中找到 org UUID。这样 federation 就被限定到了一个特定 CrewAI organization - 只有为该组织 automations 签发的 token 才会被接受。
  • Name: 任意描述性标签,例如 crewai-org-prod
  • Audience: api://AzureADTokenExchange。这是 Microsoft Entra 对 federated credentials 要求的固定 audience,也是 CrewAI Platform 会放入 JWT aud claim 的值。

点击 Add

完整细节请参见 Microsoft 文档:Configure a federated identity credential on an app

第 4 步 - 授予 App Registration 访问 Key Vault 的权限

Section titled “第 4 步 - 授予 App Registration 访问 Key Vault 的权限”

在目标 vault 上为 App Registration 授予 Key Vault Secrets User - 与 static-credentials 路径使用的角色相同。你可以使用 vault-wide(更简单)或 per-secret(最小权限)两种方式。

Vault-wide (simpler)
Terminal window
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 会授予 secrets/list 权限,而 CrewAI Platform env-var form 中的 Secret Name autocomplete 依赖它。如果你希望 autocomplete 正常工作,请选择这个 tab。

Per-secret (least privilege)
Terminal window
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 会禁用 CrewAI Platform env-var form 中的 Secret Name autocomplete(autocomplete 需要 secrets/list,而它只能在 vault scope 下授予)。请改为手动输入完整的 secret name。

Portal (UI)

对于 vault-wide assignment:

  1. 在 Azure portal 中打开你的 Key Vault。
  2. 点击 Access control (IAM)AddAdd role assignment
  3. 选择角色 Key Vault Secrets UserNext
  4. 点击 Select members,搜索 App Registration crewai-secrets-reader,然后点击 Select
  5. 点击 Review + assign

对于 per-secret assignment,请使用相同流程,但从 ObjectsSecrets → 选择某个 secret → 它自己的 Access control (IAM) 面板开始。Per-secret bindings 会禁用 autocomplete(参见上面的 Per-secret tab)。

第 5 步 - 在 Key Vault 中至少创建一个 Secret

Section titled “第 5 步 - 在 Key Vault 中至少创建一个 Secret”

如果你还没有可用于测试的 secret,可以通过 Azure CLI 创建:

Terminal window
az keyvault secret set \
--vault-name <VAULT_NAME> \
--name openai-api-key \
--value "sk-your-actual-key"

或者通过 Azure portal:

  1. 打开你的 Key Vault,进入 ObjectsSecrets
  2. 点击 Generate/Import
  3. Upload options: Manual. Name: secret 名称(例如 openai-api-key)。Secret value: 粘贴值。
  4. 点击 Create

第 6 步 - 在 CrewAI Platform 中添加 Workload Identity Configuration

Section titled “第 6 步 - 在 CrewAI Platform 中添加 Workload Identity Configuration”

在 CrewAI Platform 中,进入 SettingsWorkload Identity 并点击 Add Workload Identity Config

填写表单:

  • Name: 描述性名称,例如 azure-prod
  • Cloud Provider: Azure
  • Tenant ID: 第 2 步中的 Microsoft Entra Directory (tenant) ID
  • Client ID: 第 2 步中的 App Registration Application (client) ID。 -(可选)如果你希望它成为创建 Azure-backed secret credential 时默认选择的 WI config,请勾选 Set as default for Azure

Audience 固定为 api://AzureADTokenExchange - Microsoft Entra 对 federated credentials 要求这个精确 audience,因此表单不会显示 Audience 字段。

点击 Create

第 7 步 - 添加绑定到 WI Config 的 Secret Provider Credential

Section titled “第 7 步 - 添加绑定到 WI Config 的 Secret Provider Credential”

进入 SettingsSecret Provider Credentials 并点击 Add Credential

填写表单:

  • Name: 描述性名称,例如 azure-prod-wi
  • Provider: Azure Key Vault
  • Authentication Method: Workload Identity
  • Workload Identity Configuration: 选择你在第 6 步创建的 config。
  • Key Vault URL: vault 的 DNS hostname,例如 https://my-vault.vault.azure.net。 -(可选)勾选 Set as default credential for this provider

在 Workload Identity 下方,表单只会要求填写 Key Vault URL - static-credential 字段(Tenant ID、Client ID、Client Secret)会被刻意隐藏,因为它们不适用于这条路径;tenant + client 来自关联的 WI config。

点击 Create

保存凭据后,点击 Test Connection。对于 workload-identity 凭据,这会验证 OIDC handshake:CrewAI Platform 会生成一个 JWT,把它作为 federated client_assertion 提交给 Microsoft Entra,并确认 Entra 返回一个 vault-scoped access token。绿色结果表示 federation binding 正常。

成功的 Test Connection 说明 Federated Identity Credential 的 issuer、subject 和 audience 都匹配,并且 App Registration 可达。它不能证明 per-secret Key Vault RBAC 正确 - 对特定 secret 的 getSecret 会在环境变量解析 kickoff 时单独执行。参见 Troubleshooting 了解 handshake 失败模式。

第 9 步 - 在环境变量中引用密钥

Section titled “第 9 步 - 在环境变量中引用密钥”

就像引用其他 Secrets Manager-backed env var 一样,在 automation 上引用这个 secret。有关表单字段和行为,请参见 Using the Secrets Manager

部署运行起来后,轮换 Key Vault 中的 secret:

Terminal window
az keyvault secret set \
--vault-name <VAULT_NAME> \
--name openai-api-key \
--value "rotated value"

触发一次新的 automation kickoff。该 kickoff 的环境会看到 "rotated value" - 无需重新部署、无需 worker restart、也不必等待 TTL。

若要在 worker logs 中确认,请查找:

Workload identity config '<id>' (azure): N secret(s) resolved

这行会在每次 kickoff 时出现,并表明对 Azure Key Vault 进行了新的 getSecret 调用。

如需端到端的基于 fingerprint 的验证,请参见 Verify Rotation End-to-End

症状可能原因
Test Connection 在 handshake error 处失败federated client_assertion 被 Microsoft Entra 拒绝。验证 Federated Identity Credential 的 Issuer 是否与平台的 issuer 值完全一致,Subject 是否为 organization:<your-org-uuid>(与 JWT 的 sub claim 一致),Audience 是否为 api://AzureADTokenExchange,并确认平台的 OIDC discovery URL 可从 Entra 通过公网访问。
AADSTS70021: No matching federated identity record found for presented assertionFederated Identity Credential 的 Issuer + Subject + Audience 并未与 JWT 完全匹配。重新检查第 3 步:subject 必须是 organization:<your-org-uuid>(与 JWT 的 sub claim 一致),audience 必须是 api://AzureADTokenExchange
AADSTS700024: Client assertion is not within its valid time rangeCrewAI Platform host 的时钟与真实时间存在明显偏差。检查该 host 的 NTP。
AADSTS50013: Assertion failed signature validationMicrosoft Entra 无法验证 JWT 的签名。确认 https://<your-platform-host>/oauth2/jwks 可从公网访问并返回有效 JWKS。
Secret Name autocomplete 显示 Forbidden — does not have permission to perform action 'Microsoft.KeyVault/vaults/secrets/.../list'App Registration 的 Key Vault Secrets User role 只作用于单个 secret。请在 vault scope 下授予该 role,以允许 list data-plane action。见第 4 步。
明明 Test Connection 通过了,kickoff 仍无法解析 secretWI binding 正常,但失败的 secret 上缺少 per-secret Key Vault RBAC。请检查该特定 secret(或把 role assignment 扩展到 vault scope)上的 Key Vault Secrets User
Forbidden — request was not authorized(vault 使用旧 access policies)vault 尚未切换到 Azure RBAC。请在 vault 的 Access configuration 下把 permission model 设置为 Azure role-based access control,并重新授予第 4 步中的 role。
azure_vault_url is required for Azure secret resolution(worker logs)Secret Provider Credential 缺少 Key Vault URL。重新检查第 7 步。
轮换后的值没有在下一次 kickoff 中生效确认 automation 上的 env var 引用的是 Workload Identity-backed credential(而不是 static-keys credential)。静态路径会把值写入 deploy image。

上面的占位图对应如下文件:

  • 01-register-app.png - Azure portal 的 “Register an application” 表单,已填入 crewai-secrets-reader
  • 02-add-federated-credential.png - App Registration → Certificates & secrets → Federated credentials → Add credential,已选择 Other issuer,填写平台 issuer URL、subject organization:<uuid>、audience api://AzureADTokenExchange
  • 03-grant-vault-rbac.png - Key Vault → Access control (IAM) → Add role assignment,已选择 Key Vault Secrets User 并将 App Registration 设为成员。
  • 04-per-secret-rbac.png - 同一表单,但作用范围是单个 secret 的 IAM scope(可选的最小权限路径)。
  • 05-amp-add-wi-config-azure.png - CrewAI Platform 的 “Add Workload Identity Config” 表单,Cloud Provider = Azure,已填入 Tenant ID 和 Client ID。
  • 06-amp-wi-list-with-azure.png - Workload Identity 列表页面,创建后显示 AWS、GCP 和新的 Azure config 行。
  • 07-amp-add-credential-azure-wi.png - “Add Secret Provider Credential” 表单,Provider = Azure Key Vault,Auth = Workload Identity,已选择 WI config 并填入 Key Vault URL。