

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 排除 AWS Secrets Manager 轮换故障
<a name="troubleshoot_rotation"></a>

对于许多服务，Secrets Manager 使用 Lambda 函数来轮换密钥。有关更多信息，请参阅 [通过 Lambda 函数进行轮换](rotate-secrets_lambda.md)。Lambda 轮换函数与拥有密钥的数据库或服务以及 Secrets Manager 交互。当轮换无法按预期进行时，应先检查日 CloudWatch 志。

**注意**  
某些服务可以为您管理密钥，包括管理自动轮换。有关更多信息，请参阅 [AWS Secrets Manager 密钥的托管轮换](rotate-secrets_managed.md)。

**Topics**
+ [

## 如何对函数中的密钥轮换失败进行 AWS Lambda 故障排除
](#troubleshooting-secret-rotation-failures)
+ [

## “在环境变量中找到凭证”之后没有活动
](#troubleshoot_rotation_timing-out)
+ [

## “createSecret”之后没有活动
](#troubleshoot_rotation_createSecret)
+ [

## 错误：“不允许访问 KMS”
](#troubleshoot_rotation_kms-key)
+ [

## 错误：“Key is missing from secret JSON（密钥 JSON 中缺少密钥）”
](#tshoot-lambda-mismatched-secretvalue)
+ [

## 错误：“setSecret: Unable to log into database（setSecret：无法登录数据库）”
](#troubleshoot_rotation_setSecret)
+ [

## 错误：“无法导入模块‘lambda\$1function’”
](#tshoot-python-version)
+ [

## 将现有的轮换函数版本从 Python 3.7 升级到 Python 3.9
](#troubleshoot_rotation_python39)
+ [

## 将现有的轮换函数版本从 Python 3.9 升级到 Python 3.10
](#troubleshoot_rotation_python_310)
+ [

## AWS Lambda 秘密轮换`PutSecretValue`失败
](#troubleshoot_rotation_putsecretvalue)
+ [

## 错误：“*<arn>*在*<a rotation>*步骤中执行 lambda 时出错”
](#concurrency-related-failures)

## 如何对函数中的密钥轮换失败进行 AWS Lambda 故障排除
<a name="troubleshooting-secret-rotation-failures"></a>

如果您的 Lambda 函数遇到密钥轮换失败，请遵循以下步骤排查并解决问题。

### 可能的原因
<a name="possible-causes"></a>
+ Lambda 函数的并发执行次数不足
+ 由于轮换期间的多个 API 调用而导致出现争用情况
+ Lambda 函数逻辑不正确
+ Lambda 函数和数据库之间存在联网问题

### 一般故障排除步骤
<a name="general-troubleshooting-steps"></a>

1. 分析 CloudWatch 日志：
   + 在 Lambda 函数日志中查找特定的错误消息或意外行为
   + 验证是否正在尝试所有轮换步骤（**CreateSecret**、**SetSecret**、**TestSecret**、**FinishSecret**）

1. 审核轮换期间的 API 调用：
   + 避免在 Lambda 轮换期间对密钥进行可变 API 调用
   + 确保 **RotateSecret** 和 **PutSecretValue** 调用之间没有争用情况

1. 验证 Lambda 函数逻辑：
   + 确认你使用的是最新的密钥轮换 AWS 示例代码
   + 如果使用自定义代码，请审核代码以正确处理所有轮换步骤

1. 检查网络配置：
   + 验证安全组规则是否允许 Lambda 函数访问数据库
   + 确保 Secrets Manager 能够正确访问 VPC 端点或公有端点

1. 测试密钥版本：
   + 验证密钥的 AWSCURRENT 版本是否允许访问数据库
   + 检查 AWSPREVIOUS 或 AWSPENDING 版本是否有效

1. 清除待处理的轮换：
   + 如果轮换一直失败，请清除 AWSPENDING 暂存标签并重试轮换

1. 检查 Lambda 并发设置：
   + 验证并发设置是否适合您的工作负载
   + 如果您怀疑存在并发问题，请参阅“排查并发相关的轮换故障”部分

## “在环境变量中找到凭证”之后没有活动
<a name="troubleshoot_rotation_timing-out"></a>

如果“在环境变量中找到凭证”之后没有活动，并且任务持续时间很长，例如默认 Lambda 超时为 30000 毫秒，则 Lambda 函数可能会在尝试访问 Secrets Manager 端点时超时。

Lambda 轮换功能必须能够访问 Secrets Manager 端点。如果您的 Lambda 函数可以访问互联网，则可以使用公共端点。若要查找端点，请参阅 [AWS Secrets Manager 端点](asm_access.md#endpoints)。

如果您的 Lambda 函数在不具备互联网访问权限的 VPC 中运行，我们建议您在 VPC 内配置 Secrets Manager 服务私有端点。然后，您的 VPC 可以拦截发往公共区域端点的请求并将其重定向到私有端点。有关更多信息，请参阅 [VPC 端点（AWS PrivateLink）](vpc-endpoint-overview.md)。

或者，您可以通过向 VPC 添加 [NAT 网关](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)或[互联网网关](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html)（这将允许来自您 VPC 的流量访问公有端点），允许 Lambda 函数访问 Secrets Manager 公有端点。这会使 VPC 面临一定的风险，因为网关的 IP 地址可能会受到来自公有 Internet 的攻击。

## “createSecret”之后没有活动
<a name="troubleshoot_rotation_createSecret"></a>

以下问题可能会在 createSecret 之后导致轮换停止：

**VPC 网络 ACLs 不允许 HTTPS 流量进出。**  
有关更多信息，请参阅 *Amazon VPC 用户指南 ACLs*中的[使用网络控制子网流量](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html)。

**Lambda 函数超时配置过短，无法执行任务。**  
有关更多信息，请参阅 *AWS Lambda 开发人员指南*中的[配置 Lambda 函数选项](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html)。

**Secrets Manager VPC CIDRs 终端节点不允许 VPC 进入分配的安全组。**  
有关更多信息，请参阅《Amazon VPC 用户指南》中的[使用安全组控制到资源的流量](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)。

**Secrets Manager VPC 端点策略不允许 Lambda 使用 VPC 端点。**  
有关更多信息，请参阅 [使用 AWS Secrets Manager VPC 终端节点](vpc-endpoint-overview.md)。

**该密钥使用交替用户轮换策略，超级用户密钥由 Amazon RDS 管理，并且 Lambda 函数无法访问 RDS API。**  
对于超级用户秘密[由其他 AWS 服务管理](service-linked-secrets.md)的[交替用户轮换](rotation-strategy.md#rotating-secrets-two-users)，Lambda 轮换函数必须能够调用服务端点以获取数据库连接信息。我们建议您为数据库服务配置 VPC 端点。有关更多信息，请参阅:  
+  《*Amazon RDS 用户指南*》中的 [Amazon RDS API 和接口 VPC 端点](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/vpc-interface-endpoints.html)。
+ 《*Amazon Redshift 管理指南*》中的[使用 VPC 端点](https://docs.aws.amazon.com/redshift/latest/mgmt/enhanced-vpc-working-with-endpoints.html)。

## 错误：“不允许访问 KMS”
<a name="troubleshoot_rotation_kms-key"></a>

如果您看到 `ClientError: An error occurred (AccessDeniedException) when calling the GetSecretValue operation: Access to KMS is not allowed`，则轮换函数无权使用密钥加密所用的 KMS 密钥来将密钥解密。权限策略中可能存在将加密上下文限定为特定密钥的条件。有关所需权限的信息，请参阅 [适用于客户托管密钥的策略语句](rotating-secrets-required-permissions-function.md#rotating-secrets-required-permissions-function-cust-key-example)。

## 错误：“Key is missing from secret JSON（密钥 JSON 中缺少密钥）”
<a name="tshoot-lambda-mismatched-secretvalue"></a>

Lambda 轮换函数要求密钥值采用特定的 JSON 结构。如果显示此错误，则 JSON 可能缺少轮换函数尝试访问的密钥。有关每种密钥类型的 JSON 结构的信息，请参阅 [AWS Secrets Manager 密钥的 JSON 结构](reference_secret_json_structure.md)。

## 错误：“setSecret: Unable to log into database（setSecret：无法登录数据库）”
<a name="troubleshoot_rotation_setSecret"></a>

以下问题可能导致此错误：

**轮换函数无法访问数据库。**  
如果任务持续时间过长，例如超过 5000 毫秒，则 Lambda 轮换函数可能无法通过网络访问数据库。  
如果数据库或服务在 VPC 中的 Amazon EC2 实例上运行，建议将 Lambda 函数配置为在同一 VPC 中运行。然后轮换功能可以直接与您的服务通信。有关更多信息，请参阅[配置 VPC 访问](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html#vpc-configuring)。  
要允许 Lambda 函数访问数据库或服务，您必须确保附加到 Lambda 轮换函数的安全组允许与数据库或服务的出站连接。您还必须确保附加到数据库或服务的安全组允许来自 Lambda 轮换函数进行入站连接。

**密钥中的凭证有误。**  
如果任务持续时间过短，则 Lambda 轮换函数可能无法使用密钥中的凭证进行身份验证。使用 AWS CLI 命令使用密钥`AWSCURRENT`和`AWSPREVIOUS`版本中的信息手动登录，检查凭据[https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-secret-value.html](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-secret-value.html)。

**数据库使用 `scram-sha-256` 加密密码。**  
如果您的数据库是 Aurora PostgreSQL 版本 13 或更高版本，并且使用 `scram-sha-256` 加密密码，但轮换函数使用不支持 `scram-sha-256` 的 `libpq` 版本 9 或更旧版本，则轮换函数无法连接到数据库。  

**确定哪些数据库用户使用 `scram-sha-256` 加密**
+ 请参阅博客 [RDS for PostgreSQL 13 中的 SCRAM 身份验证](https://aws.amazon.com/blogs/database/scram-authentication-in-rds-for-postgresql-13/)中的*检查使用非 SCRAM 密码的用户*。

**确定您的轮换函数使用哪个 `libpq` 版本**

1. 在基于 Linux 的计算机上，在 Lambda 控制台上导航到您的轮换函数并下载部署包。将 zip 文件解压缩到工作目录中。

1. 在命令行上，在工作目录中运行：

   `readelf -a libpq.so.5 | grep RUNPATH`

1. 如果看到字符串 *`PostgreSQL-9.4.x`* 或任何低于 10 的主要版本，则轮换函数不支持 `scram-sha-256`。
   + 不支持 `scram-sha-256` 的轮换函数的输出：

     `0x000000000000001d (RUNPATH) Library runpath: [/local/p4clients/pkgbuild-a1b2c/workspace/build/PostgreSQL/PostgreSQL-9.4.x_client_only.123456.0/AL2_x86_64/DEV.STD.PTHREAD/build/private/tmp/brazil-path/build.libfarm/lib:/local/p4clients/pkgbuild-a1b2c/workspace/src/PostgreSQL/build/private/install/lib]`
   + 支持 `scram-sha-256` 的轮换函数的输出：

     `0x000000000000001d (RUNPATH) Library runpath: [/local/p4clients/pkgbuild-a1b2c/workspace/build/PostgreSQL/PostgreSQL-10.x_client_only.123456.0/AL2_x86_64/DEV.STD.PTHREAD/build/private/tmp/brazil-path/build.libfarm/lib:/local/p4clients/pkgbuild-a1b2c/workspace/src/PostgreSQL/build/private/install/lib]`
   + 支持 `scram-sha-256` 的轮换函数的输出：

     `0x000000000000001d (RUNPATH) Library runpath: [/local/p4clients/pkgbuild- a1b2c /workspace/build/PostgreSQL/PostgreSQL-14.x_client_only. 123456 .0/AL2_x86_64/DEV.STD.PTHREAD/build/private/tmp/brazil-path/build.libfarm/lib:/local/p4clients/pkgbuild- a1b2c /workspace/src/PostgreSQL/build/private/install/lib]`
   + 支持 `scram-sha-256` 的轮换函数的输出：

     `0x000000000000001d (RUNPATH) Library runpath: [/local/p4clients/pkgbuild- a1b2c/workspace/build/PostgreSQL/PostgreSQL- 14.x_client_only.123456.0/AL2_x86_64/DEV.STD.PTHREAD/build/private/tmp/brazil- path/build.libfarm/lib:/local/p4clients/pkgbuild- a1b2c/workspace/src/PostgreSQL/build/private/install/lib]`
如果您在 2021 年 12 月 30 日之前设置了自动密钥轮换，则轮换函数捆绑了不支持 `scram-sha-256` 的较早版本 `libpq`。为了支持 `scram-sha-256`，您需要[重新创建您的轮换函数](rotate-secrets_turn-on-for-db.md)。

**数据库需要 SSL/TLS 访问权限。**  
如果您的数据库需要 SSL/TLS 连接，但轮换函数使用未加密的连接，则轮换函数无法连接到数据库。适用于 Amazon RDS（Oracle 和 Db2 除外）和 Amazon DocumentDB 的轮换函数将自动使用安全套接字层 (SSL) 或传输层安全性协议 (TLS) 来连接到数据库（如果可用）。否则，他们将使用未加密的连接。  
如果您在 2021 年 12 月 20 日之前设置了自动密钥轮换，则轮换功能可能基于不支持的早期模板SSL/TLS. To support connections that use SSL/TLS，则需要[重新创建轮换函数](rotate-secrets_turn-on-for-db.md)。

**确定您的轮换函数的创建时间**

1. 在 Secrets Manager 控制台中 [https://console.aws.amazon.com/secretsmanager/](https://console.aws.amazon.com/secretsmanager/)，打开你的密钥。在 **Rotation configuration**（轮换配置）中的 **Lambda rotation function**（Lambda 轮换函数）下，您将看到 **Lambda function ARN**（Lambda 函数 ARN），例如，`arn:aws:lambda:aws-region:123456789012:function:SecretsManagerMyRotationFunction `。在此示例 ` SecretsManagerMyRotationFunction ` 中，从 ARN 末尾复制函数名称。

1. 在 AWS Lambda 控制台的 “**函数**” 下 [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)，将您的 Lambda 函数名称粘贴到搜索框中，选择 Enter，然后选择 Lambda 函数。

1. 在函数详细信息页面中，在 **Configuration**（配置）选项卡上的 **Tags**（标签）下，复制键 **aws:cloudformation:stack-name** 旁边的值。

1. 在 AWS CloudFormation 控制台 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) 的 **Stacks** 下，将密钥值粘贴到搜索框中，然后选择 Enter。

1. 堆栈列表将进行筛选，以便只显示创建 Lambda 轮换函数的堆栈。在 **Created date**（创建日期）列中，查看堆栈的创建日期。这是 Lambda 轮换函数的创建日期。

## 错误：“无法导入模块‘lambda\$1function’”
<a name="tshoot-python-version"></a>

如果您运行的是早期版本的 Lambda 函数，且该函数是从 Python 3.7 自动升级到更新版本的 Python 的，则可能会遇到此错误。要解决此错误，您可以将 Lambda 函数版本改回 Python 3.7，然后 [将现有的轮换函数版本从 Python 3.7 升级到 Python 3.9](#troubleshoot_rotation_python39)。要了解更多信息，请参阅 *AWS re:Post* 中的 [为什么我的 Secrets Manager Lambda 函数轮换失败并出现“找不到 pg 模块”错误？](https://repost.aws/knowledge-center/secrets-manager-lambda-rotation)。

## 将现有的轮换函数版本从 Python 3.7 升级到 Python 3.9
<a name="troubleshoot_rotation_python39"></a>

2022 年 11 月之前创建的部分轮换函数使用 Python 3.7。适用于 Python 的 AWS 软件开发工具包于 2023 年 12 月停止支持 Python 3.7。有关更多信息，请参阅 [Python 支持政策更新 AWS SDKs 和工具](https://aws.amazon.com/blogs/developer/python-support-policy-updates-for-aws-sdks-and-tools/)。要切换到使用 Python 3.9 的新轮换函数，可以在现有轮换函数中添加运行时系统属性或重新创建轮换函数。

**查找使用 Python 3.7 的 Lambda 轮换函数**

1. 登录 AWS 管理控制台 并打开 AWS Lambda 控制台，网址为[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)。

1. 在**函数**列表中，筛选 **SecretsManager**。

1. 在筛选后的函数列表中，在**运行时系统**下，查找 Python 3.7。

**Topics**
+ [

### 选项 1：使用重新创建旋转函数 CloudFormation
](#update-python-opt-1)
+ [

### 选项 2：使用更新现有旋转函数的运行时间 CloudFormation
](#update-python-opt-2)
+ [

### 选项 3：对于 AWS CDK 用户，升级 CDK 库
](#update-python-opt-3)

### 选项 1：使用重新创建旋转函数 CloudFormation
<a name="update-python-opt-1"></a>

当您使用 Secrets Manager 控制台开启轮换功能时，Secrets Manager 会使用 CloudFormation 创建必要的资源，包括 Lambda 轮换函数。如果您使用控制台开启轮换，或者使用 CloudFormation 堆栈创建了旋转功能，则可以使用相同的 CloudFormation 堆栈重新创建具有新名称的旋转函数。新函数将使用最新版本的 Python。

**查找创建旋转函数的 CloudFormation 堆栈**
+ 在 Lambda 函数的详细信息页面的**配置**选项卡上，选择**标签**。查看 **aws:cloudformation:stack-id** 旁的 ARN。

  堆栈名称已嵌入在 ARN 中，如下例所示。
  + ARN：`arn:aws:cloudformation:us-west-2:408736277230:stack/SecretsManagerRDSMySQLRotationSingleUser5c2-SecretRotationScheduleHostedRotationLambda-3CUDHZMDMBO8/79fc9050-2eef-11ed-80f0-021fb13c0537`
  + 堆栈名称：**SecretsManagerRDSMySQLRotationSingleUser5c2-SecretRotationScheduleHostedRotationLambda**

**重新创建轮换函数（CloudFormation）**

1. 在中 CloudFormation，按名称搜索堆栈，然后选择**更新**。

   如果出现建议您更新根堆栈的对话框，请选择**转到根堆栈**，然后选择**更新**。

1. 在**更新堆栈**页面上的**准备模板**下，选择**在应用程序编辑器中编辑**，然后在**在应用程序编辑器中编辑模板**下，选择**在应用程序编辑器中编辑**按钮。

1. 在应用程序编辑器中，执行以下操作：

   1. 在模板代码中，在 `SecretRotationScheduleHostedRotationLambda` 中将 `"functionName": "SecretsManagerTestRotationRDS"` 的值替换为新的函数名称，例如在 JSON 中为 `"functionName": "SecretsManagerTestRotationRDSupdated"` 

   1. 选择**更新模板**。

   1. 在**继续使用 CloudFormation** 对话框中，选择**确认并继续使用 CloudFormation**。

1. 继续完成 CloudFormation 堆栈工作流程，然后选择**提交**。

### 选项 2：使用更新现有旋转函数的运行时间 CloudFormation
<a name="update-python-opt-2"></a>

当您使用 Secrets Manager 控制台开启轮换功能时，Secrets Manager 会使用 CloudFormation 创建必要的资源，包括 Lambda 轮换函数。如果您使用控制台开启轮换，或者使用 CloudFormation 堆栈创建了旋转函数，则可以使用相同的 CloudFormation 堆栈来更新旋转功能的运行时间。

**查找创建旋转函数的 CloudFormation 堆栈**
+ 在 Lambda 函数的详细信息页面的**配置**选项卡上，选择**标签**。查看 **aws:cloudformation:stack-id** 旁的 ARN。

  堆栈名称已嵌入在 ARN 中，如下例所示。
  + ARN：`arn:aws:cloudformation:us-west-2:408736277230:stack/SecretsManagerRDSMySQLRotationSingleUser5c2-SecretRotationScheduleHostedRotationLambda-3CUDHZMDMBO8/79fc9050-2eef-11ed-80f0-021fb13c0537`
  + 堆栈名称：**SecretsManagerRDSMySQLRotationSingleUser5c2-SecretRotationScheduleHostedRotationLambda**

**更新轮换函数的运行时系统（CloudFormation）**

1. 在中 CloudFormation，按名称搜索堆栈，然后选择**更新**。

   如果出现建议您更新根堆栈的对话框，请选择**转到根堆栈**，然后选择**更新**。

1. 在**更新堆栈**页面上的**准备模板**下，选择**在应用程序编辑器中编辑**，然后在**在应用程序编辑器中编辑模板**下，选择**在应用程序编辑器中编辑**按钮。

1. 在应用程序编辑器中，执行以下操作：

   1. 在模板 JSON 中，对于 `SecretRotationScheduleHostedRotationLambda`，在 `Properties` 下的 `Parameters` 下方，添加 **"runtime": "python3.9"**。

   1. 选择**更新模板**。

   1. 在**继续使用 CloudFormation** 对话框中，选择**确认并继续使用 CloudFormation**。

1. 继续完成 CloudFormation 堆栈工作流程，然后选择**提交**。

### 选项 3：对于 AWS CDK 用户，升级 CDK 库
<a name="update-python-opt-3"></a>

如果您使用 v2.94.0 AWS CDK 之前的版本为密钥设置轮换，则可以通过升级到 v2.94.0 或更高版本来更新 Lambda 函数。有关更多信息，请参见 [AWS Cloud Development Kit (AWS CDK) v2 开发人员指南](https://docs.aws.amazon.com/cdk/v2/guide/home.html)。

## 将现有的轮换函数版本从 Python 3.9 升级到 Python 3.10
<a name="troubleshoot_rotation_python_310"></a>

Secrets Manager 正在针对 Lambda 轮换函数从 Python 3.9 过渡到 Python 3.10。要切换到使用 Python 3.10 的新轮换函数，需要遵循基于部署方法的升级路径。使用以下过程升级 Python 版本和底层依赖项。

**要查找哪些 Lambda 旋转函数使用 Python 3.9**

1. 登录 AWS 管理控制台 并打开 AWS Lambda 控制台，网址为[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)。

1. 在**函数**列表中，筛选 **SecretsManager**。

1. 在筛选后的函数列表中，在**运行时系统**下，查找 **Python 3.9**。

### 按部署方法更新路径
<a name="update-python-3.9-paths"></a>

此列表中标识的 Lambda 轮换函数可以通过 Secrets Manager 控制台、 AWS Serverless Application Repository 应用程序或 CloudFormation 转换进行部署。每种这些部署策略有着不同的更新路径。

根据函数的部署方式，使用以下过程之一更新您的 Lambda 轮换函数。

------
#### [ AWS Secrets Manager console-deployed functions ]

必须通过 AWS Secrets Manager 控制台部署新的 Lambda 函数，因为您无法手动更新现有 Lambda 函数的依赖关系。

使用以下步骤升级 AWS Secrets Manager 控制台部署的功能。

1. 打开 Secrets Manager 控制台，网址为[https://console.aws.amazon.com/secretsmanager/](https://console.aws.amazon.com/secretsmanager/)。

1. 在 **AWS Secrets Manager** 下方，选择**密钥**。选择使用希望更新的 Lambda 函数的密钥。

1. 导航到**轮换**选项卡，然后选择**更新轮换配置**选项。

1. 在**轮换函数**下，选择**创建新的 Lambda 函数**，然后为 Lambda 轮换函数输入一个名称。

   1. （可选）更新完成后，您可以测试更新后的 Lambda 函数以确认其按预期运行。在**轮换**选项卡下，选择**立即轮换密钥**以启动立即轮换。

   1. （可选）您可以在 Amazon 中查看您的函数日志和运行时使用的 Python 版本 CloudWatch。有关更多信息，请参阅*AWS Lambda 开发人员*指南中的[查看 Lambda 函数的 CloudWatch 日志](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs-view.html#monitoring-cloudwatchlogs-console)。

1. 设置新的轮换函数后，您可以删除旧的轮换函数。

------
#### [ AWS Serverless Application Repository deployments ]

以下过程说明如何升级 AWS Serverless Application Repository 部署。通过部署的 Lambda 函数 AWS Serverless Application Repository 有一个横幅，`This function belongs to an application. Click here to manage it.`其中包含指向该函数所属的 Lambda 应用程序的链接。

**重要**  
AWS Serverless Application Repository 可用性 AWS 区域 视情况而定。

使用以下过程更新 AWS Serverless Application Repository 已部署的函数。

1. 打开 AWS Lambda 控制台，网址为[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)。

1. 导航到需要更新的 Lambda 函数的**配置**选项卡。

   1. 更新已部署的 AWS Serverless Application Repository 应用程序时，您需要以下有关您的函数的信息。您可以在 Lambda 控制台中找到这些信息。
     + **Lambda 应用程序的名称**
       + 使用横幅中的链接可以找到 Lambda 应用程序的名称。例如，横幅声明以下 `serverlessrepo-SecretsManagerRedshiftRotationSingleUser`。在本示例中，名称为 `SecretsManagerRedshiftRotationSingleUser`。
     + **Lambda 轮换函数名称**
     + **Secrets Manager 端点**
       + 该端点可以在分配给 **SECRETS\$1MANAGER\$1ENDPOINT** 变量的**配置**和**环境变量**选项卡下找到。

1. 要升级 Python，必须更新无服务器应用程序的语义版本。请参阅 *AWS Serverless Application Repository 开发人员指南*中的[更新应用程序](https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-how-to-consume-new-version.html#update-applications)。

------
#### [ Custom Lambda rotation functions ]

如果您创建自定义 Lambda 轮换函数，则需要升级这些函数的每个软件包依赖项和运行时。有关更多信息，请参阅[将 Lambda 函数运行时升级到最新版本](https://repost.aws/knowledge-center/lambda-upgrade-function-runtime)。

------
#### [ AWS::SecretsManager-2024-09-16 transform macro ]

如果通过此转换部署 Lambda 函数，则[使用现有模板更新堆栈](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-direct.html)将允许您使用更新后的 Lambda 运行时。

使用以下步骤使用现有模板更新 CloudFormation 堆栈。

1. 在 [https://console.aws.amazon.com/cloudformat](https://console.aws.amazon.com/cloudformation/) ion 上打开 CloudFormation 控制台。

1. 在**堆栈**页面上，选择要更新的堆栈。

1. 在堆栈详细信息窗格上，选择**更新**。

1. 在**选择模板更新方法**中，选择**直接更新**。

1. 在**选择模板**页面上，选择**使用现有模板**。

1. 将所有其他选项保留为默认值，然后选择**更新堆栈**。

如果您在更新堆栈时遇到问题，请参阅 *CloudFormation 用户指南*中的[确定堆栈故障的原因](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/determine-root-cause-for-stack-failures.html)。

------
#### [ AWS::SecretsManager-2020-07-23 transform macro ]

如果您正在使用 `AWS::SecretsManager-2020-07-23`，我们建议您迁移到较新的转换版本。有关更多信息[，请参阅*AWS 安全*博客中的介绍增强版 AWS Secrets Manager 转换 AWS::: SecretsManager -2024-09-16](https://aws.amazon.com/blogs/security/introducing-an-enhanced-version-of-the-aws-secrets-manager-transform-awssecretsmanager-2024-09-16/)。如果您继续使用 `AWS::SecretsManager-2020-07-23`，则可能会遇到运行时版本与 Lambda 函数代码构件不匹配的错误。有关更多信息，请参阅《*CloudFormation 模板参考*》RotationSchedule HostedRotationLambda中的[AWS SecretsManager::::](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-secretsmanager-rotationschedule-hostedrotationlambda.html#cfn-secretsmanager-rotationschedule-hostedrotationlambda-runtime)。

如果您在更新堆栈时遇到问题，请参阅 *CloudFormation 用户指南*中的[确定堆栈故障的原因](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/determine-root-cause-for-stack-failures.html)。

------

**验证 Python 升级**  
要验证 Python 升级情况，请打开 Lambda 控制台 ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) 并访问**函数**页面。选择您更新的函数。在**代码源**部分下，查看目录中包含的文件，并确保 Python .so 文件是版本 `3.10`。

## AWS Lambda 秘密轮换`PutSecretValue`失败
<a name="troubleshoot_rotation_putsecretvalue"></a>

如果您在 Secrets Manager 中使用代入角色或跨账户轮换，并且在中发现了一个 CloudTrail 带有以下消息**RotationFailed**的事件：*LAMBDA\$1ARN.*Lambda 未创建 Secret 的待处理密钥*SECRET\$1ARN *版本*VERSION\$1ID *移除暂存标签并重启轮换，则需要更新 Lambda 函数才能使用`AWSPENDING`该参数。`RotationToken`<a name="troubleshoot_rotation_procedure"></a>

## 更新 Lambda 轮换函数以包括 `RotationToken`
<a name="troubleshoot_rotation_procedure"></a>

1. 下载 Lambda 函数代码
   + 打开 Lambda 控制台
   + 在导航窗格中，选择**函数**
   + 针对**函数名称**选择您的 Lambda 密钥轮换函数
   + 在**下载**中，选择**函数代码 .zip**、**AWS SAM 文件**、**两者**中的一个选项
   + 选择**确定**将该函数保存在本地计算机上。

1. 编辑 `Lambda_handler`

   在跨账户轮换的 create\$1secret 步骤中包括 rotation\$1token 参数：

   ```
   def lambda_handler(event, context):
       """Secrets Manager Rotation Template
   
       This is a template for creating an AWS Secrets Manager rotation lambda
   
       Args:
           event (dict): Lambda dictionary of event parameters. These keys must include the following:
               - SecretId: The secret ARN or identifier
               - ClientRequestToken: The ClientRequestToken of the secret version
               - Step: The rotation step (one of createSecret, setSecret, testSecret, or finishSecret)
               - RotationToken: the rotation token to put as parameter for PutSecretValue call
   
           context (LambdaContext): The Lambda runtime information
   
       Raises:
           ResourceNotFoundException: If the secret with the specified arn and stage does not exist
   
           ValueError: If the secret is not properly configured for rotation
   
           KeyError: If the event parameters do not contain the expected keys
   
       """
       arn = event['SecretId']
       token = event['ClientRequestToken']
       step = event['Step']
       # Add the rotation token
       rotation_token = event['RotationToken']
   
       # Setup the client
       service_client = boto3.client('secretsmanager', endpoint_url=os.environ['SECRETS_MANAGER_ENDPOINT'])
   
       # Make sure the version is staged correctly
       metadata = service_client.describe_secret(SecretId=arn)
       if not metadata['RotationEnabled']:
           logger.error("Secret %s is not enabled for rotation" % arn)
           raise ValueError("Secret %s is not enabled for rotation" % arn)
       versions = metadata['VersionIdsToStages']
       if token not in versions:
           logger.error("Secret version %s has no stage for rotation of secret %s." % (token, arn))
           raise ValueError("Secret version %s has no stage for rotation of secret %s." % (token, arn))
       if "AWSCURRENT" in versions[token]:
           logger.info("Secret version %s already set as AWSCURRENT for secret %s." % (token, arn))
           return
       elif "AWSPENDING" not in versions[token]:
           logger.error("Secret version %s not set as AWSPENDING for rotation of secret %s." % (token, arn))
           raise ValueError("Secret version %s not set as AWSPENDING for rotation of secret %s." % (token, arn))
       # Use rotation_token
       if step == "createSecret":
           create_secret(service_client, arn, token, rotation_token)
   
       elif step == "setSecret":
           set_secret(service_client, arn, token)
       
       elif step == "testSecret":
           test_secret(service_client, arn, token)
           
       elif step == "finishSecret":
           finish_secret(service_client, arn, token)
           
       else:
           raise ValueError("Invalid step parameter")
   ```

1. 编辑 `create_secret` 代码

   修订 `create_secret` 函数以接受并使用 `rotation_token` 参数：

   ```
   # Add rotation_token to the function
   def create_secret(service_client, arn, token, rotation_token):
   """Create the secret
   
   This method first checks for the existence of a secret for the passed in token. If one does not exist, it will generate a
   new secret and put it with the passed in token.
   
   Args:
   service_client (client): The secrets manager service client
   
   arn (string): The secret ARN or other identifier
   
   token (string): The ClientRequestToken associated with the secret version
   
   rotation_token (string): the rotation token to put as parameter for PutSecretValue call
   
   Raises:
   ResourceNotFoundException: If the secret with the specified arn and stage does not exist
   
   """
   # Make sure the current secret exists
   service_client.get_secret_value(SecretId=arn, VersionStage="AWSCURRENT")
   
   # Now try to get the secret version, if that fails, put a new secret
   try:
   service_client.get_secret_value(SecretId=arn, VersionId=token, VersionStage="AWSPENDING")
   logger.info("createSecret: Successfully retrieved secret for %s." % arn)
   except service_client.exceptions.ResourceNotFoundException:
   # Get exclude characters from environment variable
   exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
   # Generate a random password
   passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
   
   # Put the secret, using rotation_token
   service_client.put_secret_value(SecretId=arn, ClientRequestToken=token, SecretString=passwd['RandomPassword'], VersionStages=['AWSPENDING'], RotationToken=rotation_token)
   logger.info("createSecret: Successfully put secret for ARN %s and version %s." % (arn, token))
   ```

1. 更新已更新的 Lambda 函数代码

   更新您的 Lambda 函数代码后，[将其上传以轮换密钥](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-zip.html#configuration-function-update)。

## 错误：“*<arn>*在*<a rotation>*步骤中执行 lambda 时出错”
<a name="concurrency-related-failures"></a>

如果您的 Lambda 函数在指令集合循环中卡住，例如在 **CreateSecret** 和 **SetSecret** 之间，此时您遇到间歇性密钥轮换故障，则该问题可能与并发设置有关。

### 并发问题排查步骤
<a name="concurrency-troubleshooting-steps"></a>

**警告**  
由于 Lambda 函数的执行线程不足，将预置的并发参数设置为低于 10 的值可能会导致节流。有关更多信息，请参阅《 AWS Lambda AWS Lambda 开发人员指南》中的[了解预留并发和预置并发](https://docs.aws.amazon.com/lambda/latest/dg/lambda-concurrency.html#reserved-and-provisioned)。

1. 检查并调整 Lambda 并发设置：
   + 验证 `reserved_concurrent_executions` 是否设置太低（例如 1）
   + 如果使用预留并发，请将其值至少设置为 10
   + 考虑使用非预留并发以获得更大的灵活性

1. 对于预置并发：
   + 不要显式设置预配置并发参数（例如，在 Terraform 中）。
   + 如果必须设置此参数，请使用至少为 10 的值。
   + 全面测试以确保所选值适用于您的使用案例。

1. 监控和调整并发：
   + 使用以下公式计算并发：并发 =（每秒平均请求数）\$1（以秒为单位的平均请求持续时间）。有关更多信息，请参阅[估算预留并发](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html#estimating-reserved-concurrency)。
   + 观察并记录轮换期间的值，以确定适当的并发设置。
   + 请谨慎设置低并发值。如果没有足够的可用执行线程，它们可能会导致节流。

有关配置 Lambda 并发的更多信息，请参阅开发人员指南中的[配置预留并发](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html)和[配置预配置并发](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html)。 AWS Lambda 