

# 为指标设置持有者令牌身份验证
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth"></a>

**注意**  
本页将介绍 CloudWatch 指标 OTLP 端点的持有者令牌身份验证。有关 CloudWatch Logs 持有者令牌身份验证，请参阅《CloudWatch Logs 用户指南》**中的[为日志设置持有者令牌身份验证](https://docs.amazonaws.cn/AmazonCloudWatch/latest/logs/CWL_HTTP_Endpoints_BearerTokenAuth.html)。

在使用持有者令牌身份验证通过 CloudWatch OTLP 端点发送指标之前，您需要：
+ 创建具有 CloudWatch 指标权限的 IAM 用户
+ 生成服务特定凭证（API 密钥）

**重要**  
对于所有可行的工作负载，建议将 SigV4 身份验证与短期凭证结合使用。SigV4 提供了最强的安全态势。请将 API 密钥（持有者令牌）的使用限制在无法使用基于短期凭证的身份验证的场景中，例如从非 Amazon 环境、第三方供应商或不支持 Amazon SDK 的平台发送指标。当您准备将 CloudWatch 指标集成到安全要求更高的应用程序时，请切换为短期凭证。有关更多信息，请参阅《IAM 用户指南》**中的[长期访问密钥的替代方案](https://docs.amazonaws.cn/IAM/latest/UserGuide/best-practices.html#bp-workloads-use-roles)。

**重要**  
CloudWatch OTLP 端点要求使用 TLS（HTTPS）。通过纯 HTTP 发送的持有者令牌请求将被拒绝。配置客户端时，请始终使用 `https://monitoring.{{Amazon Region}}.amazonaws.com/v1/metrics`。

## 选项 1：使用 Amazon 控制台快速入门
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-QuickStart"></a>

Amazon 管理控制台提供了用于生成 OTLP 端点访问 API 密钥的简化工作流。

**使用控制台设置 OTLP 端点访问权限**

1. 登录 Amazon 管理控制台。

1. 导航到 **CloudWatch** > **设置** > **全局设置**。

1. 在 API 密钥部分中，选择**生成 API 密钥**。

1. 对于 **API 密钥过期时间**，请执行以下操作之一：
   + 选择 API 密钥的过期时间 **1**、**5**、**30**、**90** 或 **365** 天。
   + 选择**自定义持续时间**以指定自定义 API 密钥到期日期。
   + 选择**永不过期**（不推荐）。

1. 选择**生成 API 密钥**。

控制台会自动：
+ 创建具有适当权限的新 IAM 用户
+ 附加 [CloudWatchAPIKeyAccess](https://docs.amazonaws.cn/aws-managed-policy/latest/reference/CloudWatchAPIKeyAccess.html) 托管策略（包含 `cloudwatch:PutMetricData` 和 `cloudwatch:CallWithBearerToken` 权限）
+ 生成服务特定凭证（API 密钥）

**保存和验证 API 密钥**

1. 复制并安全保存所显示的凭证：
   + **API 密钥 ID**（服务特定凭证 ID）
   + **API 密钥**（持有者令牌）

   控制台还提供了在生成期间直接将 API 密钥存储在 [Amazon Secrets Manager](https://docs.amazonaws.cn/secretsmanager/latest/userguide/intro.html) 中的选项。如果您选择存储在 Secrets Manager 中，则密钥会在重置时自动更新，在删除时自动移除。
**重要**  
请立即保存 API 密钥。您之后将无法再次检索它。如果丢失，则必须生成新的 API 密钥。

1. 发送测试指标以验证设置：

   ```
   curl -X POST "https://monitoring.us-east-1.amazonaws.com/v1/metrics" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer {{YOUR_API_KEY}}" \
        -d '{"resourceMetrics":[]}'
   ```

## 选项 2：手动设置
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-ManualSetup"></a>

如果您希望更好地控制 IAM 配置或需要自定义权限，可以手动设置 OTLP 端点访问权限。

### 步骤 1：创建一个 IAM 用户
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Step1"></a>

创建用于指标摄取的 IAM 用户：

**创建用于指标摄取的 IAM 用户**

1. 登录 Amazon 管理控制台并导航到 IAM。

1. 在左侧导航窗格中，选择 **用户**。

1. 选择**创建用户**。

1. 输入用户名（例如 **cloudwatch-metrics-api-key-user**）。

1. 选择**下一步**。

1. 附加以下 IAM 策略之一：

   **选项 A：使用托管策略（推荐）**

   附加 [CloudWatchAPIKeyAccess](https://docs.amazonaws.cn/aws-managed-policy/latest/reference/CloudWatchAPIKeyAccess.html) 托管策略。

   **选项 B：创建自定义策略**

   创建并附加以下 IAM 策略：

   ```
   {
       "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
               "Sid": "CloudWatchMetricsAPIs",
               "Effect": "Allow",
               "Action": [
                   "cloudwatch:CallWithBearerToken",
                   "cloudwatch:PutMetricData"
               ],
               "Resource": "*"
           },
           {
               "Sid": "KMSDecryptForCMKDatasets",
               "Effect": "Allow",
               "Action": [
                   "kms:Decrypt"
               ],
               "Condition": {
                   "StringLike": {
                       "kms:ViaService": "cloudwatch.*.amazonaws.com",
                       "kms:EncryptionContext:aws:cloudwatch:arn": "arn:aws:cloudwatch:*:*:dataset/*"
                   }
               },
               "Resource": "arn:aws:kms:*:*:key/*"
           }
       ]
   }
   ```

1. 选择**下一步**，然后选择**创建用户**。

**注意**  
如果您计划将指标发送到使用客户自主管理型 KMS 密钥（CMK）的数据集，则需要 KMS 权限。这些条件将 KMS 访问权限限制为仅允许通过 CloudWatch 服务为数据集资源使用的密钥。

### 步骤 2：生成服务特定凭证（API 密钥）
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Step2"></a>

使用 [CreateServiceSpecificCredential](https://docs.amazonaws.cn/IAM/latest/APIReference/API_CreateServiceSpecificCredential.html) API 生成 CloudWatch 指标 API 密钥。您也可以使用 [create-service-specific-credential](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-service-specific-credential.html) Amazon CLI 命令。对于凭证期限，可以指定 1–36600 天之间的值。如果不指定凭证期限，API 密钥将不会过期。

要生成有效期为 30 天的 API 密钥，请执行下面的操作：

```
aws iam create-service-specific-credential \
    --user-name cloudwatch-metrics-api-key-user \
    --service-name cloudwatch.amazonaws.com \
    --credential-age-days 30
```

响应是一个 [ServiceSpecificCredential](https://docs.amazonaws.cn/IAM/latest/APIReference/API_ServiceSpecificCredential.html) 对象。`ServiceCredentialSecret` 值就是 CloudWatch 指标 API 密钥（持有者令牌）。

**重要**  
请安全存储 `ServiceCredentialSecret` 值。您之后将无法再次检索它。如果丢失，则必须生成新的 API 密钥。

### 步骤 3：发送指标
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Step3"></a>

您可以使用持有者令牌立即向 OTLP 端点发送指标：

```
curl -X POST "https://monitoring.us-east-1.amazonaws.com/v1/metrics" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer {{YOUR_API_KEY}}" \
     -d '{"resourceMetrics":[]}'
```

该端点同时接受 `application/json` 和 `application/x-protobuf` 内容类型。

## 控制生成和使用 CloudWatch 指标 API 密钥的权限
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Permissions"></a>

### 控制 CloudWatch 指标 API 密钥的生成
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Permissions-Generation"></a>

[`iam:CreateServiceSpecificCredential`](https://docs.amazonaws.cn/service-authorization/latest/reference/list_awsidentityandaccessmanagementiam.html#awsidentityandaccessmanagementiam-actions-as-permissions) 操作可控制服务特定密钥（例如 CloudWatch 指标 API 密钥）的生成。您可以将此操作作为一种资源，将操作范围限定为 IAM 用户，以便限制可以为其生成密钥的用户。

您可以使用以下条件密钥对 `iam:CreateServiceSpecificCredential` 操作的权限施加条件：
+ [`iam:ServiceSpecificCredentialAgeDays`](https://docs.amazonaws.cn/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#ck_ServiceSpecificCredentialAgeDays)：允许您在条件中指定密钥的过期时间（以天为单位）。
+ [`iam:ServiceSpecificCredentialServiceName`](https://docs.amazonaws.cn/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#ck_ServiceSpecificCredentialServiceName)：允许您在条件中指定服务名称。

### 控制 CloudWatch 指标 API 密钥的使用
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Permissions-Usage"></a>

`cloudwatch:CallWithBearerToken` 操作可控制 CloudWatch 指标 API 密钥的使用。为防止某个身份使用 CloudWatch 指标 API 密钥，请向与该密钥关联的 IAM 用户附加拒绝 `cloudwatch:CallWithBearerToken` 操作的策略。

**注意**  
CloudWatch 指标的持有者令牌只能与 OTLP 指标摄取端点 (`https://monitoring.{{Amazon Region}}.amazonaws.com/v1/metrics`) 结合使用。它们不能用于调用任何其他 CloudWatch API 或端点，包括查询 API（`GetMetricData`、`ListMetrics`、`DescribeAlarms`）、PromQL 查询端点、OTLP 跟踪数据端点或 OTLP 日志端点。

### 策略示例
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Permissions-Examples"></a>

**阻止身份生成和使用 CloudWatch 指标 API 密钥：**

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DenyCWMetricsAPIKeys",
            "Effect": "Deny",
            "Action": [
                "iam:CreateServiceSpecificCredential",
                "cloudwatch:CallWithBearerToken"
            ],
            "Resource": "*"
        }
    ]
}
```

**警告**  
此策略会阻止为所有支持创建服务特定凭证的 Amazon 服务创建凭证。有关更多信息，请参阅《IAM 用户指南》**中的 [IAM 用户的服务特定凭证](https://docs.amazonaws.cn/IAM/latest/UserGuide/id_credentials_service-specific-creds.html)。

**阻止身份使用 CloudWatch 指标 API 密钥：**

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action": "cloudwatch:CallWithBearerToken",
            "Resource": "*"
        }
    ]
}
```

**仅当 CloudWatch 指标密钥在 90 天内过期时，才允许创建：**

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iam:CreateServiceSpecificCredential",
            "Resource": "arn:aws:iam::123456789012:user/{{username}}",
            "Condition": {
                "StringEquals": {
                    "iam:ServiceSpecificCredentialServiceName": "cloudwatch.amazonaws.com"
                },
                "NumericLessThanEquals": {
                    "iam:ServiceSpecificCredentialAgeDays": "90"
                }
            }
        }
    ]
}
```

## 在 OpenTelemetry Collector 中使用持有者令牌
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Collector"></a>

使用持有者令牌时，不需要 `sigv4auth` 扩展。请使用 [bearertokenauth](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/bearertokenauthextension) 扩展，通过文件或环境变量安全提供 API 密钥：

```
extensions:
  bearertokenauth:
    filename: "/etc/otel/cw-api-key"

exporters:
  otlphttp:
    tls:
      insecure: false
    endpoint: https://monitoring.us-east-1.amazonaws.com/v1/metrics
    auth:
      authenticator: bearertokenauth

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    send_batch_size: 200
    timeout: 10s

service:
  extensions: [bearertokenauth]
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [otlphttp]
```

或者，您可以引用环境变量而不是文件：

```
extensions:
  bearertokenauth:
    token: "${env:CW_API_KEY}"
```

**重要**  
切勿直接在收集器配置文件中对 API 密钥进行硬编码。配置文件通常会提交到版本控制或存储在部署清单中。请使用 `filename` 从已挂载的密钥中读取，或使用 `${env:VAR}` 从 Secrets Manager 注入的环境变量中读取。

**注意**  
使用持有者令牌身份验证时，不需要 `sigv4auth` 扩展、Amazon 凭证文件、IAM 角色或 IRSA 配置。这样，收集器配置便可移植到任何环境（Amazon、本地或其他云提供商）。

## 轮换 API 密钥
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Rotation"></a>

定期轮换 API 密钥可降低未授权访问的风险。建议您制定与贵组织安全策略相符的轮换计划。

### 轮换过程
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Rotation-Process"></a>

要在不中断指标传输的情况下轮换 API 密钥，请按照以下步骤操作：

**轮换 API 密钥**

1. 为 IAM 用户创建新的（辅助）凭证：

   ```
   aws iam create-service-specific-credential \
       --user-name cloudwatch-metrics-api-key-user \
       --service-name cloudwatch.amazonaws.com \
       --credential-age-days 90
   ```
**注意**  
IAM 允许每个 IAM 用户每项服务最多拥有 2 个服务特定凭证。如果已达到此限制，请先删除或停用旧凭证，然后再创建新凭证。

1. （可选）将新凭证存储在 Amazon Secrets Manager 中，以便进行安全检索和自动轮换。

1. 更新 OpenTelemetry Collector 配置或应用程序以使用新的 API 密钥。

1. 将原始凭证设置为非活动状态：

   ```
   aws iam update-service-specific-credential \
       --user-name cloudwatch-metrics-api-key-user \
       --service-specific-credential-id {{ACCA1234EXAMPLE1234}} \
       --status Inactive
   ```

1. 验证指标传输是否未受影响。使用新密钥发送测试请求，并确认收到 HTTP 200 响应。您还可以监控应用程序现有的 CloudWatch 指标，以确认数据持续到达。

1. 确认使用新密钥成功传输后，删除之前的凭证：

   ```
   aws iam delete-service-specific-credential \
       --service-specific-credential-id {{ACCA1234EXAMPLE1234}}
   ```

### 监控密钥过期
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Rotation-Monitoring"></a>

要检查现有 API 密钥的创建日期和状态，请使用 [list-service-specific-credentials](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/list-service-specific-credentials.html) c命令：

```
aws iam list-service-specific-credentials \
    --user-name cloudwatch-metrics-api-key-user \
    --service-name cloudwatch.amazonaws.com
```

响应包含每个凭证的 `CreateDate` 和 `Status`。使用这些信息来识别即将过期或保持活动状态的时间超过轮换策略允许范围的密钥。

## 响应遭到泄露的 API 密钥
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-Compromised"></a>

如果您怀疑 API 密钥遭到泄露，请立即采取以下步骤：

**响应遭到泄露的 API 密钥**

1. **立即停用该密钥**以防止进一步的未经授权使用：

   ```
   aws iam update-service-specific-credential \
       --user-name cloudwatch-metrics-api-key-user \
       --service-specific-credential-id {{ACCA1234EXAMPLE1234}} \
       --status Inactive
   ```

1. **查看 CloudTrail 日志**以确定未经授权访问的范围。请参阅[使用 CloudTrail 记录 API 密钥使用情况](#CloudWatch-OTLP-MetricsBearerTokenAuth-CloudTrail)，了解如何启用 API 密钥使用情况审计。

1. 按照[轮换过程](#CloudWatch-OTLP-MetricsBearerTokenAuth-Rotation-Process)中所述的轮换过程**创建替换密钥**。

1. 在替换密钥就位后**删除遭到泄露的密钥**：

   ```
   aws iam delete-service-specific-credential \
       --service-specific-credential-id {{ACCA1234EXAMPLE1234}}
   ```

1. 如果您在调查期间需要立即阻止 IAM 用户访问所有持有者令牌，请**附加拒绝策略**：

   ```
   {
       "Version": "2012-10-17",		 	 	 
       "Statement": {
           "Effect": "Deny",
           "Action": "cloudwatch:CallWithBearerToken",
           "Resource": "*"
       }
   }
   ```

**注意**  
要通过 API 执行这些操作，您必须使用 Amazon 凭证进行身份验证，而不是使用 CloudWatch 指标 API 密钥。持有者令牌只能用于指标摄取，不能用于 IAM 管理操作。

您还可以使用以下 IAM API 操作来管理遭到泄露的密钥：
+ [ResetServiceSpecificCredential](https://docs.amazonaws.cn/IAM/latest/APIReference/API_ResetServiceSpecificCredential.html)：重置密钥以生成新密码，而不删除凭证。密钥必须尚未过期。

## API 密钥的安全最佳实践
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-BestPractices"></a>

遵循以下最佳实践来保护 CloudWatch 指标 API 密钥：
+ **切勿将 API 密钥嵌入源代码。**不要在应用程序代码、收集器配置文件或版本控制系统中对 API 密钥进行硬编码。请使用带有 `filename` 或 `${env:VAR}` 的 `bearertokenauth` 扩展，在运行时注入密钥。
+ **使用 Secrets Manager。**将 API 密钥存储在 [Amazon Secrets Manager](https://docs.amazonaws.cn/secretsmanager/latest/userguide/intro.html) 或等效的机密管理解决方案中。这样可以实现集中化访问控制、审计日志记录和自动轮换。
+ **为所有密钥设置过期时间。**创建 API 密钥时，始终指定 `--credential-age-days` 值。要在整个组织中强制执行最长密钥使用期限，请使用 `iam:ServiceSpecificCredentialAgeDays` IAM 条件键。
+ **应用最低权限许可。**以 [CloudWatchAPIKeyAccess](https://docs.amazonaws.cn/aws-managed-policy/latest/reference/CloudWatchAPIKeyAccess.html) 托管策略为起点，并根据需要进一步限制。
+ **启用 CloudTrail 日志记录。**通过为 `AWS::CloudWatch::Metric` 启用 CloudTrail 数据事件来审计 API 密钥使用情况。请参阅[使用 CloudTrail 记录 API 密钥使用情况](#CloudWatch-OTLP-MetricsBearerTokenAuth-CloudTrail)。
+ **使用 IAM Access Analyzer 进行监控。**使用 [IAM Access Analyzer](https://docs.amazonaws.cn/IAM/latest/UserGuide/what-is-access-analyzer.html) 来识别与 API 密钥 IAM 用户关联的未使用凭证和过于宽松的策略。
+ **定期轮换密钥。**制定轮换计划，并按照[轮换 API 密钥](#CloudWatch-OTLP-MetricsBearerTokenAuth-Rotation)中所述的过程进行操作。

## 使用 CloudTrail 记录 API 密钥使用情况
<a name="CloudWatch-OTLP-MetricsBearerTokenAuth-CloudTrail"></a>

您可以使用 Amazon CloudTrail 记录数据事件，以便摄取 CloudWatch 指标 OTLP。CloudWatch 会针对对 OTLP 端点的调用发出 `AWS::CloudWatch::Metric` 数据事件，使您能够审计指标摄取活动，包括 API 密钥使用情况。

**注意**  
您为跟踪指定的 S3 存储桶必须具有允许 CloudTrail 向其写入日志文件的存储桶策略。有关更多信息，请参阅《Amazon CloudTrail 用户指南》**中的 [CloudTrail 的 Amazon S3 存储桶策略](https://docs.amazonaws.cn/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html)。

**为 CloudWatch 指标 API 密钥使用情况启用 CloudTrail 日志记录**

1. 创建跟踪：

   ```
   aws cloudtrail create-trail \
       --name cloudwatch-metrics-api-key-audit \
       --s3-bucket-name {{my-cloudtrail-bucket}} \
       --region us-east-1
   ```

1. 配置高级事件选择器以捕获 CloudWatch 指标写入（摄取）数据事件：

   ```
   aws cloudtrail put-event-selectors \
       --region us-east-1 \
       --trail-name cloudwatch-metrics-api-key-audit \
       --advanced-event-selectors '[{
           "Name": "CloudWatch Metrics write data events",
           "FieldSelectors": [
               { "Field": "eventCategory", "Equals": ["Data"] },
               { "Field": "resources.type", "Equals": ["AWS::CloudWatch::Metric"] },
               { "Field": "readOnly", "Equals": ["false"] }
           ]
       }]'
   ```

1. 启动跟踪日志记录：

   ```
   aws cloudtrail start-logging \
       --name cloudwatch-metrics-api-key-audit \
       --region us-east-1
   ```

`readOnly: false` 筛选条件将日志记录限制为写入操作（PutMetricData），其中包括所有 OTLP 摄取调用。要在这些事件中识别持有者令牌使用情况，请查询跟踪日志（通过 Athena 或 CloudTrail Lake），并按与 API 密钥关联的 IAM 用户名（例如 `cloudwatch-metrics-api-key-user`）进行筛选。OTLP 摄取事件在其事件有效载荷中包含 `AdditionalEventData.protocol`，其值为 `OTLP`。您可以在事后查询中使用它，以将其与经典的 PutMetricData SDK 调用区分开来。