开始使用出站身份联合验证 - AWS Identity and Access Management

开始使用出站身份联合验证

本指南向您展示如何为您的 AWS 账户启用出站身份联合验证以及如何获取您的第一个 JSON Web 令牌(JWT)(使用 GetWebIdentityToken API)。您将启用该功能,与外部服务建立信任关系,配置 IAM 权限,并使用 AWS CLI 或适用于 Python 的 AWS SDK(Boto3)请求令牌。

先决条件

在开始之前,请确保您满足以下条件:

  • 已安装最新版本的 AWS CLI 或 Python 3.8(或更高版本)和 Boto3(适用于 AWS SDK 示例)

  • 可以在其中配置信任关系的外部服务帐户(例如外部云提供商、SaaS 提供商或测试应用程序)

注意
  • GetWebIdentityToken API 在 STS 全局端点上不可用。

  • GetWebIdentityToken API 生成的 JSON Web 令牌(JWT)不能用于通过 OpenID Connect(OIDC)联合身份验证登录 AWS(通过 AssumeRoleWithWebIdentity API)。

为您的账户启用出站身份联合验证

必须先启用出站身份联合验证,然后才能请求令牌。您可以使用 AWS 管理控制台启用该功能,也可以使用 EnableOutboundWebIdentityFederation API 以编程方式启用该功能。

使用 AWS CLI

aws iam enable-outbound-web-identity-federation

使用适用于 Python 的 AWS SDK

import boto3 # Create IAM client iam_client = boto3.client('iam') # Enable outbound identity federation response = iam_client.enable_outbound_web_identity_federation() print(f"Feature enabled. Issuer URL: {response['IssuerUrl']}") print(f"Status: {response['Status']}")

使用 AWS 控制台

导航到 IAM,然后在左侧导航菜单的访问管理部分下选择账户设置

启用该功能后,请记下您的账户特定发布者 URL。在外部服务中配置信任关系时,您将使用此 URL。您也可以根据需要使用 GetOutboundWebIdentityFederationInfo API 检索此发布者 URL。

在外部服务中建立信任关系

将外部服务配置为信任并接受由您的 AWS 账户发布的令牌。具体步骤因服务而有所不同,但通常包括:

  • 将您的 AWS 账户发布者 URL 注册为可信身份提供商

  • 配置要验证的声明(受众、主题模式)

  • 将令牌声明映射到外部服务中的权限

有关详细的配置说明,请参阅外部服务文档。

配置 IAM 权限

创建一个 IAM 策略,授予调用 GetWebIdentityToken API 的权限,然后将该策略附加到需要生成令牌的 IAM 角色。

此示例策略授予生成令牌的权限,但具有特定限制。其仅允许为受众“https://api.example.com”请求令牌,并且强制规定最长令牌生命周期为 5 分钟(300 秒)。有关可用于强制执行令牌属性的条件键列表,请参阅 IAM 和 AWS STS 条件上下文密钥

示例 IAM 策略

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:GetWebIdentityToken", "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "sts:IdentityTokenAudience": "https://api.example.com" }, "NumericLessThanEquals": { "sts:DurationSeconds": 300 } } } ] }

请求您的第一个 JSON Web 令牌(JWT)

您可以使用 GetWebIdentityToken API 请求 JSON Web 令牌。调用 API 时可以指定以下参数:

  • 受众(必填):令牌的预期接收者。该值填充 JWT 中的“aud”声明。外部服务验证此声明,以确保令牌是为其准备的。

  • SigningAlgorithm(必填):用于对令牌进行签名的加密算法。有效值为 ES384 和 RS256。使用 ES384 可获得最佳安全性和性能,或使用 RS256 可实现与不支持 ECDSA 的系统更广泛的兼容性。

  • DurationSeconds(可选):令牌生命周期(以秒为单位)。有效值范围为 60 至 3600。默认值为 300(5 分钟)。我们建议缩短令牌生命周期以提高安全性。

  • 标签(可选):要作为自定义声明包含在令牌中的键值对列表。外部服务可以使用这些声明进行精细授权。

该 API 会返回以下字段:

  • IdentityToken:已签名的 JWT,以 base64url 编码字符串的形式表示。将此令牌包含在对外部服务的请求中。

  • 过期:令牌过期时的 UTC 时间戳。

使用 AWS CLI

aws sts get-web-identity-token \ --audience "https://api.example.com" \ --signing-algorithm ES384 \ --duration-seconds 300 \ --tags Key=team,Value=data-engineering \ Key=environment,Value=production \ Key=cost-center,Value=analytics

使用适用于 Python 的 AWS SDK

import boto3 sts_client = boto3.client('sts') response = sts_client.get_web_identity_token( Audience=['https://api.example.com'], DurationSeconds=300, SigningAlgorithm='RS256', Tags=[ {'Key': 'team', 'Value': 'data-engineering'}, {'Key': 'environment', 'Value': 'production'}, {'Key': 'cost-center', 'Value': 'analytics'} ] ) token = response['WebIdentityToken']

您也可以使用标准 JWT 库(例如 PyJWT、Python-jose for Python、Nimbus JOSE+JWT for Java 或 jwt.io 之类的调试程序)解码 JWT 以检查其内容。有关令牌中包含的声明的更多信息,请参阅了解令牌声明

将令牌与外部服务一起使用

收到令牌后,将其包含在对外部服务的请求中。方法因服务而有所不同,但大多数服务都接受 Authorization 标头中的令牌。外部服务应实现令牌验证逻辑,以在授予对 AWS 工作负载的访问权限之前,从发布者的知名端点获取 JWKS 密钥,验证令牌的签名并验证基本声明。

从 OpenID Connect(OIDC)端点获取验证密钥和元数据

您 AWS 账户唯一的发布者 URL 可托管 OpenID Connect(OIDC)发现端点,其中包含令牌验证所需的验证密钥和元数据。

OIDC 发现端点 URL 包含一些提供商用于验证令牌的元数据。网址为:

{issuer_url}/.well-known/openid-configuration

JWKS(JSON Web 密钥集)端点包含用于验证令牌签名的密钥。网址为:

{issuer_url}/.well-known/jwks.json

使用 curl 获取 JWKS

curl https://{issuer_url}/.well-known/jwks.json

响应:

{ "keys": [ { "kty": "EC", "use": "sig", "kid": "key-id-1", "alg": "ES384", "crv": "P-384", "x": "base64-encoded-x-coordinate", "y": "base64-encoded-y-coordinate" }, { "kty": "RSA", "use": "sig", "kid": "key-id-2", "n": "base64-encoded-modulus", "e": "AQAB" } ] }

使用适用于 Python 的 AWS SDK

import requests # Fetch Openid Configuration open_id_config_response = requests.get("https://{issuer_url}/.well-known/openid-configuration") open_id_config = open_id_config_response.json() # Fetch JWKS jwks_response = requests.get("https://{issuer_url}/.well-known/jwks.json") jwks = jwks_response.json()

我们建议缓存这些密钥,以避免每次验证令牌时都需要重新获取。

基本声明验证

  • 主题(sub):验证主题声明是否包含预期的 IAM 主体 ARN 模式。

  • 过期(exp):确保令牌未过期。JWT 库通常会自动处理此问题。

  • 受众(aud):验证受众是否匹配您的预期值。这样可以防止原本用于其他服务的令牌与您的令牌混用。

  • 发布者(iss):验证发布者是否匹配您信任的 AWS 账户。维护可信发布者 URL 列表。

应尽可能验证其他 AWS 特定声明,以在外部服务中实现精细访问控制。例如,验证 org_id 声明以限制 AWS Organization 中 IAM 主体的访问权限,选中 principal_tags 以强制执行基于属性的访问控制(例如仅允许生产环境或特定团队),或者验证 lambda_source_function_arn 或 ec2_instance_source_vpc 等会话上下文声明以根据计算资源限制访问权限。有关令牌中所包含声明的完整列表,请参阅了解令牌声明