使用 AWS 参数存储在 Laravel 中管理秘密
发布于 作者: Chris Fidao
秘密是您不想公开暴露的值,例如 API 凭据或私钥。
在 Laravel 中,这些通常是添加到 .env
文件中的值。有时它们是私钥,可能是为 Laravel Passport 生成的,或为 GitHub 应用程序下载的。
管理这些秘密的方式很大程度上取决于您的部署过程。Forge 允许您直接从服务器加载和编辑 .env
文件。对于更多自定义托管解决方案,您可能会将 .env
文件保存在 S3 存储桶中,并在部署期间下载它们。
一个更安全的解决方案(但仍然易于使用!)用于管理秘密是 AWS 参数存储。
还有一个 AWS 服务,其名称恰如其分地叫做 Secrets Manager。
Secrets Manager 具有更多功能,但您可能并不一定需要或想要它们来满足此用例。它也更昂贵。 参数存储定价在此处。 Secrets Manager 定价在此处。
使用参数存储
参数存储是一个键值存储。它是更大的 AWS Systems Manager (SSM) 服务的一部分。
它有很多功能!我们将介绍管理 Laravel 应用程序秘密所需的内容,包括
- 存储加密的值
- 存储大值
- 创建参数
- 检索参数
- 安全性(IAM 权限)
存储加密的值
以下是您可以存储的值类型
- 字符串
- 字符串列表(本质上是一个字符串数组)
- 安全字符串
我们将使用 SecureString
,它适合存储秘密。使用此类型将加密参数值。需要加密的值使用 KMS 服务(密钥管理服务)来提供用于加密的密钥对。
您可以在 KMS 中创建和管理自己的密钥,或者您可以使用默认密钥,该密钥是为您管理的。
创建自己的密钥可以让您更精细地控制谁有权访问使用该密钥加密的数据。KMS 用于 AWS 中的所有加密事项 - 例如加密的 EBS 驱动器、参数存储和 Secrets Manager。
在本例中,我使用的是默认 KMS 密钥。是否应该使用它取决于您的团队规模以及谁应该能够访问您组织内的这些秘密。
存储大值
参数的定价取决于参数的数量以及您通过 API 调用访问它们的频率。 有两个层级 - “标准”和“高级”。
标准层级限制为 10,000 个参数,每个参数不超过 4 KB。这些参数是免费的(尽管 API 使用仍会收费)。
高级参数限制为 100,000 个参数,但每个参数限制为 8 KB,并具有额外的安全功能。每个参数每月收取费用。
由于我们将把整个 .env
文件保存到一个参数中,因此可能会超过 4 KB 的限制。 然后您可能需要使用高级参数或将单个秘密(键/值)保存到单独的参数中。
创建参数
要将秘密存储到参数存储中,我们将使用 AWS CLI 命令 ssm put-parameter
。
这里我们存储了整个 .env
文件
aws ssm put-parameter \ --name /cloudcasts/staging/env \ --type SecureString \ --value file://.env
需要注意一些事项
- 参数的
name
使用 参数层次结构,这对于对参数进行分类以及执行安全策略很有用。- 例如,我们的
env
参数位于staging
环境的cloudcasts
“命名空间”中
- 例如,我们的
- 我们使用
SecureString
的type
,但我们没有通过--key-id
标志定义 KMS 密钥。这将使用我们工作所在的区域中的默认 KMS 密钥 - 我们使用方便的
file://path/to/file.ext
方法告诉 AWS CLI 在本地文件中查找参数的内容
这将加密并将我们的秘密存储到参数存储中!
生成您的 .env 文件
我喜欢在每次部署时获取秘密的新副本(重建 .env
文件)。
如果您想了解如何在 AWS 上创建完全自动化的自动扩展基础设施,请查看 CloudCasts 上的简单自动扩展课程!在该课程中,我们在部署期间使用参数存储来检索秘密。
如果您的秘密动态更改(在部署之外),您可能需要更动态的东西。无论如何,我避免做的一件事是将参数保存到“构建工件”(例如应用程序的 .zip
档案)中。如果这些构建工件存储在公开位置(例如,启用了公开访问权限的 S3 存储桶),您可能会泄露重要的秘密。
要构建新的 .env
文件(可能在部署期间),我们可以使用 ssm get-parameter
命令
aws ssm get-parameter \ --with-decryption \ --name /cloudcasts/staging/env \ --output text \ --query 'Parameter.Value' > .env
需要注意的事项
- 我们使用
--with-decryption
标志,因此我们收到的值将被解密- 如果不使用默认 KMS 密钥,则调用此命令的用户需要有权获取 KMS 密钥
- 我们通过
--output text
将结果输出为text
- 我们使用
--query
标志来仅检索解密的值(而不是您通常会获得的所有元数据) - 我们将输出重定向到当前目录中的
.env
文件,就像我们运行echo "foo" > .env
一样
--output
和 --query
标志适用于所有 AWS CLI 命令。您可以在 此处找到有关这些标志和其他技巧的更多信息。
处理大型 .env 文件
如果您有一个大型的 .env
文件,并且已将各个秘密分离到它们自己的参数中,您可能希望追加到您的 .env
文件,而不是覆盖它。
例如,您的基本 .env
文件可能在一个参数中,但一些较长的秘密可能在其他参数中。您可以执行以下操作
# Create the initial .env fileaws ssm get-parameter \ --with-decryption \ --name /cloudcasts/staging/base-env \ --output text \ --query 'Parameter.Value' > .env # Append a long secret to .env for each# additional secretSOME_LONG_SECRET_VALUE=$(aws ssm get-parameter \ --with-decryption \ --name /cloudcasts/staging/SOME_LONG_SECRET \ --output text \ --query 'Parameter.Value') echo "SOME_LONG_SECRET=\"$SOME_LONG_SECRET_VALUE\"" >> .env
这里没什么花哨的!只需为每个秘密不断追加到 .env 文件即可。
IAM 权限
用于调用 get-parameter
的 IAM 用户或角色可以使用 多种方法 进行锁定。使用层次结构名称(例如 /cloudcasts/staging/env
)可以帮助我们锁定与特定应用程序和环境相关的秘密。
例如,我可能有一个用于与在staging
环境中部署cloudcasts
应用程序相关的自动化的 IAM 角色。我可以像这样设置角色的 IAM 策略
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParameter" ], "Resource": "arn:aws:ssm:us-east-2:012345678910:parameter/cloudcasts/staging/*" } ]}
因此,在us-east-2
中,在帐户 ID 012345678910
上,具有上述 IAM 策略的角色可以在以/cloudcasts/staging
开头的参数上运行GetParameter
(注意使用通配符)。