

# 开始使用出站身份联合验证
<a name="id_roles_providers_outbound_getting_started"></a>

本指南向您展示如何为您的 AWS 账户启用外站身份联合验证以及如何获取您的第一个 JSON Web 令牌（JWT）（使用 [GetWebIdentityToken](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetWebIdentityToken.html) API）。您将启用该功能，与外部服务建立信任关系，配置 IAM 权限，并使用 AWS CLI 或适用于 Python 的 AWS SDK（Boto3）请求令牌。

## 先决条件
<a name="outbound-federation-prerequisites"></a>

在开始之前，请确保您满足以下条件：
+ 已安装最新版本的 AWS CLI 或 Python 3.8（或更高版本）和 Boto3（适用于 AWS SDK 示例）
+ 可以在其中配置信任关系的外部服务帐户（例如外部云提供商、SaaS 提供商或测试应用程序）

**注意**  
`GetWebIdentityToken` API 在 STS 全局端点上不可用。
`GetWebIdentityToken` API 生成的 JSON Web 令牌（JWT）不能用于通过 OpenID Connect（OIDC）联合身份验证登录 AWS（通过 [AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) API）。

## 为您的账户启用外站身份联合验证
<a name="enable-outbound-federation"></a>

必须先启用外站身份联合验证，然后才能请求令牌。您可以使用 AWS 管理控制台启用该功能，也可以使用 [EnableOutboundWebIdentityFederation](https://docs.aws.amazon.com/IAM/latest/APIReference/API_EnableOutboundWebIdentityFederation.html) API 以编程方式启用该功能。

### 使用 AWS CLI
<a name="enable-using-cli"></a>

```
aws iam enable-outbound-web-identity-federation
```

### 使用适用于 Python 的 AWS SDK
<a name="enable-using-sdk"></a>

```
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 控制台
<a name="enable-using-console"></a>

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

![“账户设置”菜单项在左侧导航栏的“访问管理”部分中突出显示。](http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/images/outbound-screen-1.png)


启用该功能后，请记下您的账户特定发布者 URL。在外部服务中配置信任关系时，您将使用此 URL。您也可以根据需要使用 [GetOutboundWebIdentityFederationInfo](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetOutboundWebIdentityFederationInfo.html) API 检索此发布者 URL。

![外站身份联合验证界面显示“已启用”状态，带有“禁用”按钮和令牌发布者 URL。](http://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/images/outbound-screen-2.png)


## 在外部服务中建立信任关系
<a name="establish-trust-relationship"></a>

将外部服务配置为信任并接受由您的 AWS 账户发布的令牌。具体步骤因服务而有所不同，但通常包括：
+ 将您的 AWS 账户发布者 URL 注册为可信身份提供商
+ 配置要验证的声明（受众、主题模式）
+ 将令牌声明映射到外部服务中的权限

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

## 配置 IAM 权限
<a name="configure-iam-permissions"></a>

创建一个 IAM 策略，授予调用 [GetWebIdentityToken](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetWebIdentityToken.html) API 的权限，然后将该策略附加到需要生成令牌的 IAM 角色。

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

### 示例 IAM 策略
<a name="example-iam-policy"></a>

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

## 请求您的第一个 JSON Web 令牌（JWT）
<a name="request-first-jwt"></a>

您可以使用 [GetWebIdentityToken](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetWebIdentityToken.html) API 请求 JSON Web 令牌。调用 API 时可以指定以下参数：
+ **受众（必填）：**令牌的预期接收者。该值填充 JWT 中的“aud”声明。外部服务验证此声明，以确保令牌是为其准备的。
+ **SigningAlgorithm（必填）：**用于对令牌进行签名的加密算法。有效值为 ES384 和 RS256。使用 ES384 可获得最佳安全性和性能，或使用 RS256 可实现与不支持 ECDSA 的系统更广泛的兼容性。
+ **DurationSeconds（可选）：**令牌生命周期（以秒为单位）。有效值范围为 60 至 3600。默认值为 300（5 分钟）。我们建议缩短令牌生命周期以提高安全性。
+ **标签（可选）：**要作为自定义声明包含在令牌中的键值对列表。外部服务可以使用这些声明进行精细授权。

该 API 会返回以下字段：
+ **IdentityToken：**已签名的 JWT，以 base64url 编码字符串的形式表示。将此令牌包含在对外部服务的请求中。
+ **过期：**令牌过期时的 UTC 时间戳。

### 使用 AWS CLI
<a name="using-aws-cli"></a>

```
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
<a name="using-aws-sdk-python"></a>

```
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 以检查其内容。有关令牌中包含的声明的更多信息，请参阅[了解令牌声明](id_roles_providers_outbound_token_claims.md)。

## 将令牌与外部服务一起使用
<a name="use-token-with-external-service"></a>

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

## 从 OpenID Connect（OIDC）端点获取验证密钥和元数据
<a name="fetch-verification-keys"></a>

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

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

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

JWKS（JSON Web 密钥集）端点包含用于验证令牌签名的密钥。网址为：

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

### 使用 curl 获取 JWKS
<a name="fetch-jwks-curl"></a>

```
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
<a name="fetch-using-sdk"></a>

```
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()
```

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

### 基本声明验证
<a name="essential-claim-validations"></a>
+ **主题（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 等会话上下文声明以根据计算资源限制访问权限。有关令牌中所包含声明的完整列表，请参阅[了解令牌声明](id_roles_providers_outbound_token_claims.md)。