AWS Secrets Manager 轮换问题排查 - AWS Secrets Manager

AWS Secrets Manager 轮换问题排查

对于许多服务,Secrets Manager 使用 Lambda 函数来轮换密钥。有关更多信息,请参阅 通过 Lambda 函数进行轮换。Lambda 轮换函数与拥有密钥的数据库或服务以及 Secrets Manager 交互。如果轮换没有按预期方式运行,应先检查 CloudWatch 日志。

注意

某些服务可以为您管理密钥,包括管理自动轮换。有关更多信息,请参阅 AWS Secrets Manager 密钥的托管轮换

如何排查 AWS Lambda 函数中的密钥轮换失败

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

可能的原因

  • Lambda 函数的并发执行次数不足

  • 由于轮换期间的多个 API 调用而导致出现争用情况

  • Lambda 函数逻辑不正确

  • Lambda 函数和数据库之间存在联网问题

一般故障排除步骤

  1. 分析 CloudWatch 日志:

    • 在 Lambda 函数日志中查找特定的错误消息或意外行为

    • 验证是否正在尝试所有轮换步骤(CreateSecretSetSecretTestSecretFinishSecret

  2. 审核轮换期间的 API 调用:

    • 避免在 Lambda 轮换期间对密钥进行可变 API 调用

    • 确保 RotateSecretPutSecretValue 调用之间没有争用情况

  3. 验证 Lambda 函数逻辑:

    • 确认正在使用密钥轮换的最新 AWS 示例代码

    • 如果使用自定义代码,请审核代码以正确处理所有轮换步骤

  4. 检查网络配置:

    • 验证安全组规则是否允许 Lambda 函数访问数据库

    • 确保 Secrets Manager 能够正确访问 VPC 端点或公有端点

  5. 测试密钥版本:

    • 验证密钥的 AWSCURRENT 版本是否允许数据库访问

    • 检查 AWSPREVIOUS 或 AWSPENDING 版本是否有效

  6. 清除待处理的轮换:

    • 如果轮换持续失败,请清除 AWSPENDING 暂存标签并重试轮换

  7. 检查 Lambda 并发设置:

    • 验证并发设置是否适合您的工作负载

    • 如果您怀疑存在并发问题,请参阅“排查并发相关的轮换故障”部分

“在环境变量中找到凭证”之后没有活动

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

Lambda 轮换功能必须能够访问 Secrets Manager 端点。如果您的 Lambda 函数可以访问互联网,则可以使用公共终端节点。若要查找端点,请参阅 AWS Secrets Manager 端点

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

或者,您可以通过向 VPC 添加 NAT 网关互联网网关(这将允许来自您 VPC 的流量访问公有端点),允许 Lambda 函数访问 Secrets Manager 公有端点。这会使 VPC 面临一定的风险,因为网关的 IP 地址可能会受到来自公有 Internet 的攻击。

“createSecret”之后没有活动

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

VPC 网络 ACL 不允许 HTTPS 流量进出。

有关更多信息,请参阅 Amazon VPC 用户指南中的使用网络 ACL 控制指向子网的流量

Lambda 函数超时配置过短,无法执行任务。

有关更多信息,请参阅 AWS Lambda 开发人员指南中的配置 Lambda 函数选项

Secrets Manager VPC 端点不允许在分配的安全组入口处使用 VPC CIDR。

有关安全组的更多信息,请参阅《Amazon VPC 用户指南》中的使用安全组控制到资源的流量

Secrets Manager VPC 端点策略不允许 Lambda 使用 VPC 端点。

有关更多信息,请参阅 使用 AWS Secrets Manager VPC 端点

该密钥使用交替用户轮换策略,超级用户密钥由 Amazon RDS 管理,并且 Lambda 函数无法访问 RDS API。

对于超级用户秘密由其他 AWS 服务管理交替用户轮换,Lambda 轮换函数必须能够调用服务端点以获取数据库连接信息。我们建议您为数据库服务配置 VPC 端点。有关更多信息,请参阅:

错误:“不允许访问 KMS”

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

错误:“Key is missing from secret JSON(密钥 JSON 中缺少密钥)”

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

错误:“setSecret: Unable to log into database(setSecret:无法登录数据库)”

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

轮换函数无法访问数据库。

如果任务持续时间过长,例如超过 5000 毫秒,则 Lambda 轮换函数可能无法通过网络访问数据库。

如果数据库或服务在 VPC 中的 Amazon EC2 实例上运行,建议将 Lambda 函数配置为在同一 VPC 中运行。然后轮换功能可以直接与您的服务通信。有关更多信息,请参阅配置 VPC 访问

要允许 Lambda 函数访问数据库或服务,您必须确保附加到 Lambda 轮换函数的安全组允许与数据库或服务的出站连接。您还必须确保附加到数据库或服务的安全组允许来自 Lambda 轮换函数进行入站连接。

密钥中的凭证有误。

如果任务持续时间过短,则 Lambda 轮换函数可能无法使用密钥中的凭证进行身份验证。借助 AWS CLI 命令 get-secret-value 使用密钥的 AWSCURRENTAWSPREVIOUS 版本中的信息手动登录,以检查凭证。

数据库使用 scram-sha-256 加密密码。

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

确定哪些数据库用户使用 scram-sha-256 加密
确定您的轮换函数使用哪个 libpq 版本
  1. 在基于 Linux 的计算机上,在 Lambda 控制台上导航到您的轮换函数并下载部署包。将 zip 文件解压缩到工作目录中。

  2. 在命令行上,在工作目录中运行:

    readelf -a libpq.so.5 | grep RUNPATH

  3. 如果看到字符串 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,您需要重新创建您的轮换函数

数据库需要 SSL/TLS 访问权限。

如果您的数据库需要 SSL/TLS 连接,但轮换函数使用了未加密的连接,则轮换函数无法连接到数据库。适用于 Amazon RDS(Oracle 和 Db2 除外)和 Amazon DocumentDB 的轮换函数将自动使用安全套接字层 (SSL) 或传输层安全性协议 (TLS) 来连接到数据库(如果可用)。否则,他们将使用未加密的连接。

注意

如果您在 2021 年 12 月 20 日之前设置了自动密钥轮换,则您的轮换函数可能基于不支持 SSL/TLS 的较早模板。为了支持使用 SSL/TLS 的连接,您需要重新创建您的轮换函数

确定您的轮换函数的创建时间
  1. 在 Secrets Manager 控制台 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 末尾复制函数名称。

  2. 在 AWS Lambda 控制台 https://console.aws.amazon.com/lambda/ 中的 Functions(函数)下,将您的 Lambda 函数名称粘贴到搜索框中,按 Enter 键,然后选择相应的 Lambda 函数。

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

  4. 在 AWS CloudFormation 控制台 https://console.aws.amazon.com/cloudformation 中的 Stacks(堆栈)下,将键值粘贴在搜索框中,然后按 Enter 键。

  5. 堆栈列表将进行筛选,以便只显示创建 Lambda 轮换函数的堆栈。在 Created date(创建日期)列中,查看堆栈的创建日期。这是 Lambda 轮换函数的创建日期。

错误:“无法导入模块‘lambda_function’”

如果您运行的是早期版本的 Lambda 函数,且该函数是从 Python 3.7 自动升级到更新版本的 Python 的,则可能会遇到此错误。要解决此错误,您可以将 Lambda 函数版本改回 Python 3.7,然后 将现有的轮换函数版本从 Python 3.7 升级到 Python 3.9。要了解更多信息,请参阅 AWS re:Post 中的 为什么我的 Secrets Manager Lambda 函数轮换失败并出现“找不到 pg 模块”错误?

将现有的轮换函数版本从 Python 3.7 升级到 Python 3.9

2022 年 11 月之前创建的部分轮换函数使用 Python 3.7。适用于 Python 的 AWS SDK 已于 2023 年 12 月停止支持 Python 3.7。有关更多信息,请参阅 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/

  2. 函数列表中,筛选 SecretsManager

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

选项 1:使用 CloudFormation 重新创建轮换函数

当您使用 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 中,按名称搜索堆栈,然后选择更新

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

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

  3. 在应用程序编辑器中,执行以下操作:

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

    2. 选择更新模板

    3. 继续使用 CloudFormation 对话框中,选择确认并继续使用 CloudFormation

  4. 继续完成 CloudFormation 堆栈工作流,然后选择提交

选项 2:使用 CloudFormation 更新现有轮换函数的运行时系统

当您使用 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 中,按名称搜索堆栈,然后选择更新

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

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

  3. 在应用程序编辑器中,执行以下操作:

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

    2. 选择更新模板

    3. 继续使用 CloudFormation 对话框中,选择确认并继续使用 CloudFormation

  4. 继续完成 CloudFormation 堆栈工作流,然后选择提交

选项 3:AWS CDK 用户升级 CDK 库

如果您使用 v2.94.0 之前版本的 AWS CDK 设置了密钥轮换,则可以通过升级到 v2.94.0 或更高版本来更新 Lambda 函数。有关更多信息,请参见 AWS Cloud Development Kit (AWS CDK) v2 开发人员指南

将现有的轮换函数版本从 Python 3.9 升级到 Python 3.10

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

查找使用 Python 3.9 的 Lambda 轮换函数
  1. 登录到 AWS 管理控制台,然后通过以下网址打开 AWS Lambda 控制台:https://console.aws.amazon.com/lambda/

  2. 函数列表中,筛选 SecretsManager

  3. 在筛选后的函数列表中,在运行时系统下,查找 Python 3.9

按部署方法更新路径

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

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

AWS Secrets Manager console-deployed functions

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

使用以下过程升级 AWS Secrets Manager 控制台部署的函数。

  1. 通过 https://console.aws.amazon.com/secretsmanager/ 打开 Secrets Manager 控制台。

  2. AWS Secrets Manager 下方,选择密钥。选择使用希望更新的 Lambda 函数的密钥。

  3. 导航到轮换选项卡,然后选择更新轮换配置选项。

  4. 轮换函数下,选择创建新的 Lambda 函数,然后为 Lambda 轮换函数输入一个名称。

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

    2. (可选)您可以在 Amazon CloudWatch 中查看函数日志和在运行时使用的 Python 版本。有关更多信息,请参阅 AWS Lambda 开发人员指南中的查看适用于 Lambda 函数的 CloudWatch Logs

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

AWS Serverless Application Repository deployments

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

重要

AWS Serverless Application Repository 的可用性取决于 AWS 区域。

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

  1. 通过 https://console.aws.amazon.com/lambda/ 打开 AWS Lambda 控制台。

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

    1. 更新已部署的 AWS Serverless Application Repository 应用程序时,您需要以下有关函数的信息。您可以在 Lambda 控制台中找到这些信息。

      • Lambda 应用程序的名称

        • 使用横幅中的链接可以找到 Lambda 应用程序的名称。例如,横幅声明以下 serverlessrepo-SecretsManagerRedshiftRotationSingleUser。在本示例中,名称为 SecretsManagerRedshiftRotationSingleUser

      • Lambda 轮换函数名称

      • Secrets Manager 端点

        • 该端点可以在分配给 SECRETS_MANAGER_ENDPOINT 变量的配置环境变量选项卡下找到。

  3. 要升级 Python,必须更新无服务器应用程序的语义版本。请参阅 AWS Serverless Application Repository 开发人员指南中的更新应用程序

Custom Lambda rotation functions

如果您创建自定义 Lambda 轮换函数,则需要升级这些函数的每个软件包依赖项和运行时。有关更多信息,请参阅将 Lambda 函数运行时升级到最新版本

AWS::SecretsManager-2024-09-16 transform macro

如果通过此转换部署 Lambda 函数,则使用现有模板更新堆栈将允许您使用更新后的 Lambda 运行时。

按照以下过程使用现有模板更新 CloudFormation 堆栈。

  1. 通过以下网址打开 CloudFormation 控制台:https://console.aws.amazon.com/cloudformation

  2. 堆栈页面上,选择要更新的堆栈。

  3. 在堆栈详细信息窗格上,选择更新

  4. 选择模板更新方法中,选择直接更新

  5. 选择模板页面上,选择使用现有模板

  6. 将所有其他选项保留为默认值,然后选择更新堆栈

如果您在更新堆栈时遇到问题,请参阅 CloudFormation 用户指南中的确定堆栈故障的原因

AWS::SecretsManager-2020-07-23 transform macro

如果您正在使用 AWS::SecretsManager-2020-07-23,我们建议您迁移到较新的转换版本。有关更多信息,请参阅 AWS 安全博客中的 AWS Secrets Manager 转换的增强版本简介:AWS::SecretsManager-2024-09-16 。如果您继续使用 AWS::SecretsManager-2020-07-23,则可能会遇到运行时版本与 Lambda 函数代码构件不匹配的错误。有关更多信息,请参阅 CloudFormation 模板参考中的 AWS::SecretsManager::RotationSchedule HostedRotationLambda

如果您在更新堆栈时遇到问题,请参阅 CloudFormation 用户指南中的确定堆栈故障的原因

验证 Python 升级

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

带有 PutSecretValue 失败的 AWS Lambda 密钥轮换

如果您在 Secrets Manager 中使用代入角色或跨账户轮换,并且在 CloudTrail 中发现带有以下消息的 RotationFailed 事件:未由 Lambda LAMBDA_ARN 创建密钥 SECRET_ARN 的待处理密钥版本 VERSION_ID。移除 AWSPENDING 暂存标签并重新开始轮换,然后您需要更新 Lambda 函数以使用 RotationToken 参数。

更新 Lambda 轮换函数以包括 RotationToken

  1. 下载 Lambda 函数代码

    • 打开 Lambda 控制台

    • 在导航窗格中,选择函数

    • 针对函数名称选择您的 Lambda 密钥轮换函数

    • 下载中,选择函数代码 .zipAWS SAM 文件两者中的一个选项

    • 选择确定将该函数保存在本地计算机上。

  2. 编辑 Lambda_handler

    在跨账户轮换的 create_secret 步骤中包括 rotation_token 参数:

    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")
  3. 编辑 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))
  4. 更新已更新的 Lambda 函数代码

    更新您的 Lambda 函数代码后,将其上传以轮换密钥

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

并发问题排查步骤

警告

由于 Lambda 函数的执行线程不足,将预置的并发参数设置为低于 10 的值可能会导致节流。有关更多信息,请参阅《AWS Lambda AWS Lambda 开发人员指南》中的了解预留并发和预置并发

  1. 检查并调整 Lambda 并发设置:

    • 验证 reserved_concurrent_executions 是否设置太低(例如 1)

    • 如果使用预留并发,请将其值至少设置为 10

    • 考虑使用非预留并发以获得更大的灵活性

  2. 对于预置并发:

    • 不要显式设置预配置并发参数(例如,在 Terraform 中)。

    • 如果必须设置此参数,请使用至少为 10 的值。

    • 全面测试以确保所选值适用于您的使用案例。

  3. 监控和调整并发:

    • 使用以下公式计算并发:并发 =(每秒平均请求数)*(以秒为单位的平均请求持续时间)。有关更多信息,请参阅估算预留并发

    • 观察并记录轮换期间的值,以确定适当的并发设置。

    • 请谨慎设置低并发值。如果没有足够的可用执行线程,它们可能会导致节流。

有关配置 Lambda 并发的更多信息,请参阅《AWS Lambda 开发人员指南》中的配置预留并发配置预配置并发