发布于 2026-01-06 14 阅读
0

你们把 Lambda 函数的凭据保存在哪里?

你们把 Lambda 函数的凭据保存在哪里?

如果您的 Lambda 函数需要访问数据库(或任何其他需要凭据的服务),您将该配置存储在哪里以及如何存储?

最近我们一直在迭代我们的 MVP,应用程序的需求和规模有所增长,我们一直在讨论如何安全地处理不同环境/阶段的数据库配置以及相关的用户/密码。

有很多种可能性,我们来看其中一些:

只需将主机名、用户名和密码硬编码到文件中即可。

没有

请不要这样。我真的需要告诉你为什么吗?

使用 .env 文件——该文件已提交到仓库中。

两者都不

尽管这种方案可能提供更大的灵活性,但仍然非常糟糕。任何能够访问你代码仓库的人都能立即看到你的凭据。

使用 .secrets 文件(基本上就是上面的 .env 文件,但通过serverless secrets 插件加密)。

嗯,也许吧。

这是我们最初采取的快速方法,但效果并不理想,因为:

  • Lambda 函数部署完成后,凭证会在 AWS UI 控制台中清晰可见(环境变量在部署时已嵌入到代码中)。
  • 有人误将解密文件上传的风险很高。
  • 我们不得不在多个使用类似凭据的存储库中复制这些文件。
  • 最重要的是,出现了一个问题——我们应该把解密这些秘密的密码存储在哪里
plugins:
  - serverless-secrets-plugin
custom:
  secrets: ${file(secrets.${self:provider.stage}.yml)}
Enter fullscreen mode Exit fullscreen mode

在 serverless.yml 文件中使用 SSM 加密的环境变量

好多了,但是嗯……

这比 secrets-plugin 更进一步,AWS Systems Manager Parameter Store允许您摆脱文件,只需一个配置即可供多个 Lambda 函数/存储库共享,并且可以通过 AWS UI 控制台或 AWS CLI 快速更新,但它也有同样的缺点:

  • 配置值以明文形式存储在 Lambda 环境变量中——您可以在 AWS Lambda 控制台中看到它们——如果该函数被攻击者攻破(攻击者将可以访问 process.env),那么他们也能够轻松找到解密后的值——(此视频解释了具体方法)。
  • 由于您将代码与环境变量一起部署,因此如果您需要更改配置,则需要重新部署每个 Lambda 函数以传播所有更改。
custom:
  supersecret: ${ssm:/aws/reference/secretsmanager/secret_ID_in_Secrets_Manager~true}
Enter fullscreen mode Exit fullscreen mode

在运行时访问 SSM 或 SecretsManager(并使用缓存)

好多了

将您的凭据安全地加密存储在 Systems Manager Parameter Store 或Secrets Manager中(后者还支持自动轮换),并在运行时访问它们。
然后配置您的无服务器 YAML 文件,通过 IAMRole 策略授予 Lambda 函数访问权限:

iamRoleStatements:
 - Effect: Allow
        Action:
         - ssm:GetParameter
        Resource:"arn:aws:ssm:YOUR_REGION:YOUR_ACCOUNT_ID:parameter/YOUR_PARAMETER"
Enter fullscreen mode Exit fullscreen mode

您可以设置越来越细粒度的权限级别。

"arn:aws:ssm:*:*:parameter/*"
"arn:aws:ssm:YOUR_REGION:YOUR_ACCOUNT_ID:parameter/*"
"arn:aws:ssm:YOUR_REGION:YOUR_ACCOUNT_ID:parameter/YOUR_PARAMETER-*"
"arn:aws:ssm:YOUR_REGION:YOUR_ACCOUNT_ID:parameter/YOUR_PARAMETER-SOME_MORE_SPECIFIC"
Enter fullscreen mode Exit fullscreen mode

上面的代码直接指定了您的 ARN/区域/帐户 - 如果您想要更灵活的方式,您可以设置权限以自动获取这些值:

iamRoleStatements:
 - Effect: Allow
        Action:
         - ssm:GetParameter    
        Resource:
         - Fn::Join:
          - ':'
          - - arn:aws:ssm
            - Ref: AWS::Region
            - Ref: AWS::AccountId
            - parameter/YOUR_PARAMETER-*
Enter fullscreen mode Exit fullscreen mode

由于 SecretsManager 与 ParameterStore 集成,您可以通过 SSM 访问您的密钥,只需在您的密钥前加上 `<key>` 即可。aws/reference/secretsmanager/

如果您开始修改这些权限(尤其是在 UI 控制台中编辑策略而不是重新部署 Lambda 函数时,可能需要一些时间。通常只需几秒钟,但也可能需要 2-5 分钟)。

一旦您授予 Lambda 函数访问密钥的权限,您就可以指定一个环境变量,以便根据环境/阶段,简单地告诉 Lambda 函数在运行时加载哪些凭据:

  custom:  
      credentialsKey:
        production: YOUR-PRODUCTION-CREDENTIALS-KEY
        development: YOUR-DEV-CREDENTIALS-KEY
        other: YOUR-OTHER-CREDENTIALS-KEY

functions:
  environment: 
    SECRETS_KEY:${self:custom.credentialsKey}
Enter fullscreen mode Exit fullscreen mode

这是一个巧妙的小技巧,可以为无服务器部署应用条件判断。简单来说,就是告诉无服务器架构你有三个密钥:一个用于生产环境,一个用于开发环境,一个用于所有其他阶段。
然后在 Lambda 函数的环境节点中,根据当前部署阶段设置密钥。如果当前阶段与列表中的某个变量名匹配,则使用该密钥;否则,将回退到另一个密钥。

然后,在你的 Lambda 函数中,你只需要从 SSM 或 SecretsManager 加载凭据并连接到你的数据库即可。

const ssm = new AWS.SSM();
const params = {
  Name: process.env.SECRETS_KEY,
  WithDecryption: true 
};
ssm.getParameter(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data.Parameter.Value);    // here you have your values!
});
Enter fullscreen mode Exit fullscreen mode

请记住要实施某种缓存机制,这样在重用 Lambda 容器时,就可以避免从 AWS 加载密钥(从而避免产生额外费用)。

我想指出的一点是,SSM 要求在实例化时定义 aws-region。如您所见,我并没有传递该值。这是因为该值process.env.AWS_REGION会自动从 AWS SDK 读取,并且该环境变量由 serverless offline 设置。

在您编写集成测试尝试加载密钥之前,您无需执行任何操作——我们添加了一些测试,以确保每次部署后,该环境阶段的密钥都可在 SecretsManager 上获取。在这种情况下,您必须将该变量传递给集成测试(请记住手动将其传递给集成测试)。

这是我们的 npm 脚本(我们使用AVA进行测试,使用Instanbul/nyc进行代码覆盖率测试):

"test:integration": "AWS_REGION=eu-west-1 SECRETS_KEY=MY_KEY_DEVSTAGE nyc ava tests-integration/**/*.*"
Enter fullscreen mode Exit fullscreen mode

对于这种常见的(或者说基本/根本性的)特性,您还有其他处理方法吗?


更多相关资源:
https://docs.aws.amazon.com/en_us/systems-manager/latest/userguide/integration-ps-secretsmanager.html
https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-variables-using-aws-secrets-manager

文章来源:https://dev.to/dvddpl/where-do-you-keep-credentials-for-your-lambda-functions-5dno