使用无服务器在部署阶段(CodePipeline)将机密传递给 lambda?

Passing secrets to lambda during deployment stage (CodePipeline) with Serverless?

我有一个以 GitHub 作为源的 CodePipeline,已设置。我试图在 CodePipeline 执行的部署阶段将单个秘密参数(在本例中为 Stripe 秘密密钥,当前在 .env 文件中定义 -> 下面的解释)传递给特定的 Lambda,但没有成功。

我的部署阶段基本上是一个运行 deployment.sh 脚本的 CodeBuild 项目:

#! /bin/bash npm install -g serverless@1.60.4 serverless deploy --stage $env -v -r eu-central-1

解释:

我试过用 serverless-dotenv-plugin 来做这件事,它在本地完成部署时起到了作用,但是当它通过 CodePipeline 完成时,returns lambda 的执行出错,并且一个原因:

由于 CodePipeline 的源设置为 GitHub(未提交 .env 文件),只要将更改提交到 git 存储库,就会触发 CodePipeline 的执行。当它到达部署阶段时,所有节点模块都已安装(serverless-dotenv-plugin 以及它们)并且当 serverless deploy --stage $env -v -r eu-central-1 命令执行时 serverless-dotenv-plugin 将搜索存储我的秘密的 .env 文件,不会找到它,因为没有 .env 文件,因为我们超出了 "local" 范围,当需要此秘密的 lambda 触发时,它将抛出如下错误:

所以我的问题是,是否可以使用 dotenv/serverless-dotenv-plugin 来实现,还是应该放弃这种方法?我应该使用 SSM Parameter Store 还是 Secrets Manager?如果是,有人可以解释一下吗? :)

因此,在进一步研究这个主题后,我认为我找到了解决方案。 SSM Parameter Store 与 Secrets Manager 是一个完全不同的主题,但就我的目的而言,SSM Paremeter Store 是我选择用于解决此问题的一个选择。基本上可以通过两种方式完成。

1.使用 AWS Parameter Store

只需在您的 AWS Parameter Store 控制台中添加一个秘密,然后将 serverless.yml 中的值引用为 Lambda 环境变量即可。 Serverless Framework 能够在部署时从您的 AWS Parameter Store 账户获取值。

provider: environement: stripeSecretKey: ${ssm:stripeSecretKey}

最后,您可以像以前一样在代码中引用它:

const stripe = Stripe(process.env.stripeSecretKey);

优点: 这可以与本地 .env 文件一起用于本地和远程使用,同时保持您的 Lambda 代码相同,即。 process.env.stripeSecretKey

缺点: 由于秘密被解密,然后在部署时设置为 Lambda 环境变量,如果您转到 Lambda 控制台,您将能够看到秘密值在纯文本中。 (这有点表明存在一些安全问题)

这让我想到了第二种方法,我发现它更安全,我最终选择了它:

2。存储在AWS Parameter Store,运行时解密 为避免在您的 AWS Lambda 控制台中以纯文本形式公开秘密,您可以改为在运行时解密它们。方法如下:

  • 按照上述步骤在您的 AWS Parameter Store 控制台中添加密钥。

  • 更改您的 Lambda 代码以直接调用参数存储并在运行时解密值:

    import stripePackage from 'stripe'; const aws = require('aws-sdk'); const ssm = new aws.SSM();

    const stripeSecretKey = ssm.getParameter( {Name: 'stripeSecretKey', WithDecryption: true} ).promise(); const stripe = stripePackage(stripeSecretKey.Parameter.Value);

(小提示:如果你的Lambda定义为async函数,一定要使用await 关键字在 ssm.getParameter(...).promise(); )

之前

优点:您的秘密在任何时候都不会以纯文本形式公开。

缺点: 您的 Lambda 代码确实变得有点复杂,并且会增加延迟,因为它需要从存储中获取值。 (但考虑到它只有一个参数而且是免费的,我想这是一个很好的权衡)

作为结论,我只想提一下,所有这些工作都需要您调整 lambda 的策略,以便它可以访问 Systems Manager 和您存储在 Parameter Store 中的秘密,但这很容易通过 CloudWatch 检查。

希望这对某人有所帮助,编码愉快 :)