【问题标题】:Can I force CloudFormation to resolve values from Secrets Manager?我可以强制 CloudFormation 解析来自 Secrets Manager 的值吗?
【发布时间】:2020-04-26 23:00:51
【问题描述】:

在以下(简称 CloudFormation 模板)中,我尝试配置 AWS Lambda 函数以从注入其环境的 AWS Secrets Manager 中获取值:

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          SECRET_KEY: !Sub '{{resolve:secretsmanager:${Secret}:SecretString:KEY}}'

  Secret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: 'very-secret-thing'
      SecretString: '{"KEY":"dummy"}'

使用此模板创建堆栈时,一切都按预期进行。然后我去更改 CloudFormation 之外的秘密值,因为我真的不希望将秘密签入源代码控制。这是完全可能的,documentation 暗示,只要我避免在模板中更改 SecretString 的虚拟值,后续 CloudFormation 堆栈更新就不会触及密钥的值。

因此,在 AWS 控制台中设置实际密钥后,我需要触发 Lambda 函数的重新部署,以便 CloudFormation 解析新的密钥值并在函数的环境中设置。我该怎么做?

执行aws cloudformation deploy 失败并显示以下消息:No changes to deploy。

我怀疑 CloudFormation 将模板的“原始”版本与上次部署的版本进行比较,而没有首先解析对 Secrets Manager 的引用。是这样吗?是否有一些技巧可以强制提前取消引用?

脚注:我很清楚以这种方式使用 Secrets Manager 会导致密钥值在 AWS Lambda 控制台中可见,并且在运行时从 Secrets Manager 获取值会更安全方法。这恰好超出了我希望做的事情的范围。

【问题讨论】:

  • 当 Cloudformation 引用机密管理器或 ssm 等安全值时,它引用的是 literal dynamic reference string source。过去我也遇到过 lambda 未更新的类似问题。最简单的方法是更新您的代码 uri 以强制更新,但这并不理想。另一件事是lambda versioning,但在不更改代码的情况下强制更新时也有很多问题。

标签: amazon-web-services amazon-cloudformation aws-secrets-manager


【解决方案1】:

您可以人为地更改AWS::Serverless::Function 资源上的其他内容,以在您进行部署时强制其更新。

比如说,一个时间戳:

Parameters:
  DeployTimestamp: { Type: String }

Resources:
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          SECRET_KEY: !Sub '{{resolve:secretsmanager:${Secret}:SecretString:KEY}}'
          SECRET_KEY_UPDATED: !Ref DeployTimestamp

假设您通过脚本进行部署,那么您每次都会执行aws cloudformation deploy --parameter-overrides "DeployTimestamp=$(date)" 之类的操作来更改值。

当然,这样做的缺点是该函数将更新每个部署,即使密钥尚未更新。如果这让您感到困扰,您可以更花哨并注入aws secretsmanager describe-secret --query LastChangedDate 作为参数而不是当前时间。

【讨论】:

    【解决方案2】:

    您说读取 Lambda 中的值超出了范围,但这确实是正确的解决方案。它不仅提高了安全性,而且允许 Lambda 在密钥轮换时获取最新值。

    如果您在处理程序之外(即在初始化期间)读取密钥,则读取次数会最小化。如果这是连接到数据库的 java lambda,您还可以使用 secrets manager jdbc wrapper,它会自动获取密钥。

    【讨论】:

    • 一点背景知识:我正在查看数百个现有的 Lambda 函数,它们都通过环境获取它们的秘密(通常只是半敏感的)。我希望将这些函数导入 CloudFormation,对于此任务,改进每个函数以在运行时从 Secrets Manager 获取密钥将是一个重要的范围蔓延。我希望这有助于解释原因。
    • 读取秘密值也是有代价的。将模板中的值作为环境变量引用可以最大限度地降低成本。我确实希望有一种方法可以强制重新部署 CloudFormation 模板,即使模板本身没有更改。
    猜你喜欢
    • 2021-03-17
    • 2021-04-19
    • 2022-01-03
    • 2019-06-11
    • 2019-11-10
    • 2017-03-15
    • 2021-12-26
    • 2019-09-24
    • 2022-01-14
    相关资源
    最近更新 更多