AWS Workload Identity(OIDC Federation)
本指南通过 Workload Identity Federation 配置 AWS Secrets Manager 作为密钥 provider:CrewAI Platform 会生成短期 OIDC tokens,通过 STS 换取 AWS 凭据,然后读取你的密钥 - 全程不会在任何地方存放长期 AWS access key。
运行时如何工作
Section titled “运行时如何工作”- 部署 worker 从 CrewAI Platform 请求一个新的 OIDC JWT。
- worker 使用你下方设置的 IAM role 调用
sts:AssumeRoleWithWebIdentity,并提交这个 JWT。 - AWS STS 会根据 CrewAI Platform 的公开 OIDC issuer 验证 JWT(因此你的 platform 安装必须能被 AWS 访问),然后返回短期 AWS credentials。
- worker 使用这些 credentials 调用
secretsmanager:GetSecretValue。 - 获取到的值会在本次 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 字段就是 AWS 会注册为受信任 OIDC provider 的 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 步会用到它。
第 2 步 - 将 CrewAI Platform 注册为 IAM OIDC Identity Provider
Section titled “第 2 步 - 将 CrewAI Platform 注册为 IAM OIDC Identity Provider”打开 IAM → Identity providers console,然后点击 Add provider。
- Provider type: OpenID Connect。
- Provider URL: 第 1 步中的
issuer值(例如https://app.crewai.com)。 - Audience:
sts.amazonaws.com
点击 Add provider。
或者使用 CLI:
aws iam create-open-id-connect-provider \ --url "https://<your-platform-host>" \ --client-id-list "sts.amazonaws.com" \ --thumbprint-list "$(echo | openssl s_client -servername <your-platform-host> -connect <your-platform-host>:443 2>/dev/null | openssl x509 -fingerprint -noout -sha1 | cut -d= -f2 | tr -d ':')"从输出中复制 OpenIDConnectProviderArn(或者在控制台中复制 provider 的 ARN)。第 3 步会用到它。
第 3 步 - 创建 IAM Role
Section titled “第 3 步 - 创建 IAM Role”将下面内容保存为 trust-policy.json,并替换 <YOUR_ACCOUNT_ID>、<your-platform-host>(issuer host,不要带 https:// 或 http://,例如 app.crewai.com)以及 <YOUR_CREWAI_ORG_UUID>(来自前提条件):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::<YOUR_ACCOUNT_ID>:oidc-provider/<your-platform-host>" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "<your-platform-host>:aud": "sts.amazonaws.com", "<your-platform-host>:sub": "organization:<YOUR_CREWAI_ORG_UUID>" } } } ]}创建 role:
aws iam create-role \ --role-name crewai-secrets-reader \ --assume-role-policy-document file://trust-policy.json从输出中复制 Role Arn - 这就是你的 aws_role_arn。你会在第 6 步把它填入 CrewAI Platform。
第 4 步 - 创建并附加用于 Secrets Manager + KMS 访问的 IAM policy
Section titled “第 4 步 - 创建并附加用于 Secrets Manager + KMS 访问的 IAM policy”将下面内容保存为 secrets-policy.json,并把占位符替换成你的 account ID、region、secret-name prefix 以及用于加密这些密钥的 KMS key ARN:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "SecretsManagerListForUI", "Effect": "Allow", "Action": "secretsmanager:ListSecrets", "Resource": "*" }, { "Sid": "SecretsManagerRead", "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": "arn:aws:secretsmanager:<REGION>:<YOUR_ACCOUNT_ID>:secret:<SECRET_NAME_PREFIX>-*" }, { "Sid": "KMSDecrypt", "Effect": "Allow", "Action": [ "kms:Decrypt" ], "Resource": "arn:aws:kms:<REGION>:<YOUR_ACCOUNT_ID>:key/<KMS_KEY_ID>" } ]}SecretsManagerListForUI 为 Environment Variables 表单中的 Secret Name autocomplete 和凭据上的 Test Connection 按钮提供支持。secretsmanager:ListSecrets 只接受 Resource: "*" - 在 IAM 层面它是 account-scoped。
你可以用 CLI(最简单的是 inline policy)或者控制台 UI 将 policy 附加到 role;如果你想在多个 role 之间复用同一套权限,请使用 Managed policy 标签页创建可复用的命名 policy。
aws iam put-role-policy \ --role-name crewai-secrets-reader \ --policy-name SecretsManagerRead \ --policy-document file://secrets-policy.json这会把 policy 内联附加到 role 上。Inline policy 与 role 绑定,不能复用到其他 role。
POLICY_ARN=$(aws iam create-policy \ --policy-name CrewAISecretsReader \ --policy-document file://secrets-policy.json \ --query 'Policy.Arn' --output text)
aws iam attach-role-policy \ --role-name crewai-secrets-reader \ --policy-arn "$POLICY_ARN"Managed policy 是一个独立的 IAM resource,可以附加到多个 role 上。
- 打开 IAM → Roles console 并选择 crewai-secrets-reader。
- 在 Permissions 标签页,点击 Add permissions → Create inline policy。
- 切换到 JSON 编辑器并粘贴
secrets-policy.json的内容。 - 点击 Next,给 policy 起一个名字(例如
SecretsManagerRead),然后点击 Create policy。
如果你想创建可复用的 managed policy,请改用 IAM → Policies → Create policy,然后从 role 的 Permissions 标签页把它附加到 role。
第 5 步 - 在 AWS 中至少创建一个 Secret
Section titled “第 5 步 - 在 AWS 中至少创建一个 Secret”如果你还没有要测试的 secret,现在创建一个:
aws secretsmanager create-secret \ --region <REGION> \ --name crewai-test-keyword \ --secret-string "hello from aws"或者通过 AWS Secrets Manager console → Store a new secret。
第 6 步 - 在 CrewAI Platform 中添加 Workload Identity Configuration
Section titled “第 6 步 - 在 CrewAI Platform 中添加 Workload Identity Configuration”在 CrewAI Platform 中,进入 Settings → Workload Identity 并点击 Add Workload Identity Config。
填写表单:
- Name: 描述性名称,例如
aws-prod。 - Cloud Provider:
AWS。 - AWS Role ARN: 第 3 步中的 Role Arn。
- AWS Region: 密钥所在 region,例如
us-east-1。 -(可选)勾选 Set as default for AWS,这样当你创建 AWS-backed secret credential 时就会默认选中这个 WI config。
点击 Create。
第 7 步 - 添加绑定到 WI Config 的 Secret Provider Credential
Section titled “第 7 步 - 添加绑定到 WI Config 的 Secret Provider Credential”进入 Settings → Secret Provider Credentials 并点击 Add Credential。
填写表单:
- Name: 描述性名称,例如
aws-prod-wi。 - Provider:
AWS Secrets Manager。 - Authentication Method:
Workload Identity(而不是 static keys / AssumeRole)。 - Workload Identity Configuration: 选择你在第 6 步创建的 config(例如
aws-prod)。 -(可选)勾选 Set as default credential for this provider。
在 Workload Identity 下方,表单只会要求填写 AWS Region - static-credential 字段(Access Key ID、Secret Access Key、Role ARN、External ID)会被刻意隐藏,因为它们不适用于这条路径;role ARN 来自关联的 WI config。
点击 Create。
第 8 步 - 测试连接
Section titled “第 8 步 - 测试连接”保存凭据后,点击 Test Connection。对于 workload-identity 凭据,这会验证 OIDC handshake:CrewAI Platform 会生成一个 JWT,通过 sts:AssumeRoleWithWebIdentity 与 AWS STS 交换它,并确认返回的 credentials 能对假设的 role 调用 sts:GetCallerIdentity。绿色结果表示 federation binding 正常。
成功的 Test Connection 说明 trust policy、OIDC provider 注册以及 audience 条件都正确连接好了。它不能证明每个 secret 的 IAM 都正确 - 对特定 secret ARN 的 secretsmanager:GetSecretValue 会在环境变量解析 kickoff 时单独执行。参见 Troubleshooting 了解 handshake 失败模式。
第 9 步 - 在环境变量中引用密钥
Section titled “第 9 步 - 在环境变量中引用密钥”现在你可以在 automation 上引用这个 secret,就像引用其他 Secrets Manager-backed env var 一样。有关表单字段和行为,请参见 Using the Secrets Manager。
WI-backed 与 static-keys-backed env vars 的唯一差异是读取密钥的时间:
- WI-backed: 每次 automation kickoff 都会重新读取 secret value。
- Static-keys-backed: secret value 会在部署时读取并写入部署镜像。
第 10 步 - 验证轮换
Section titled “第 10 步 - 验证轮换”部署运行起来后,轮换 AWS 中的 secret:
aws secretsmanager update-secret \ --region <REGION> \ --secret-id crewai-test-keyword \ --secret-string "rotated value"触发一次新的 automation kickoff。该 kickoff 的环境会看到 "rotated value" - 无需重新部署、无需 worker restart、也不必等待 TTL。
若要在日志中确认(如果你能访问 worker),请查找:
Workload identity config '<id>' (aws): N secret(s) resolved这行会在每次 kickoff 时出现,并表明对 AWS 进行了新的 GetSecretValue 调用。
| 症状 | 可能原因 |
|---|---|
| Test Connection 在 handshake error 处失败 | sts:AssumeRoleWithWebIdentity 调用被拒绝。验证 trust policy 中的 federated principal ARN 是否引用了 oidc-provider/<your-platform-host>(host 不要带 https:// 或 http://,也不要结尾斜杠),audience condition 是否严格等于 sts.amazonaws.com,sub condition 是否匹配你的 CrewAI organization UUID,并确认平台的 OIDC discovery URL 可从 AWS 通过公网访问。 |
InvalidIdentityToken: Couldn't retrieve verification key from your identity provider | AWS STS 无法访问你的 CrewAI Platform host 以获取 JWKS。确认该 host 可以从 AWS 互联网访问、OIDC discovery URL 返回 200,并且 JWKS endpoint 可达。 |
AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity | trust policy 不匹配。重新检查第 3 步:federated principal ARN 必须包含 oidc-provider/<your-platform-host>(host 不要带 https:// 或 http://,也不要结尾斜杠),audience condition 必须严格等于 sts.amazonaws.com,并且 sub condition 必须等于 organization:<YOUR_CREWAI_ORG_UUID>。 |
Secret Name autocomplete 显示 AccessDenied: secretsmanager:ListSecrets | role 缺少带有 Resource: "*" 的 secretsmanager:ListSecrets。请添加第 4 步中的 SecretsManagerListForUI statement。 |
| 明明 Test Connection 通过了,kickoff 仍无法解析 secret | WI binding 正常,但失败的 secret 上缺少资源范围 IAM。请检查该特定 secret ARN 和 KMS key 上的 secretsmanager:GetSecretValue 与 kms:Decrypt 权限。 |
RegionDisabledException / no secrets found | Workload Identity Config 中的 region 与 secret 所在 region 不一致。重新检查第 6 步。 |
| 轮换后的值没有在下一次 kickoff 中生效 | 确认 automation 上的 env var 引用的是 Workload Identity-backed credential(而不是 static-keys credential)。静态路径会把值写入 deploy image。 |