在 AWS CodePipeline 中处理 运行 时间和构建时间机密
Handling run time and build time secrets in AWS CodePipeline
我们正在处理为使用 AWS CodePipeline 构建并部署到 ECS 的应用程序提供构建时间和 运行 时间机密的问题。
最终,我们的愿景是为我们的每个应用程序创建一个通用管道,以实现以下目标:
- 访问完全分离
- app-a-pipeline 中的服务无法访问任何凭据或使用 app-b-pipeline 中使用的任何密钥,反之亦然
- 指定开发人员的秘密管理
- 只有负责 app-a 的开发人员可以读取和写入 app-a 的秘密
这里是手头的问题:
- 我们的一些应用程序需要访问私有存储库以在构建时解决依赖关系
例如,我们的 java 应用程序需要访问私有 Maven 存储库才能成功构建
- 我们的一些应用程序在 运行 时需要数据库访问凭据
例如,servlet 容器 运行 连接我们的应用程序需要一个 .xml 配置文件,其中包含用于查找和访问数据库的凭据
还有一些注意事项:
- 我们的代码库位于 public 存储库中。我们不想通过将秘密的明文或密文放入我们的存储库来暴露秘密
- 我们不想将 运行时间秘密烘焙到我们在 CodeBuild 中创建的 Docker 图像中,即使 ECR 访问受到限制
- ECS 资源的 Cloudformation 模板及其关联的参数文件以明文形式驻留在 public 存储库中。这消除了通过参数将 运行 时间秘密传递给 ECS Cloudformation 模板的可能性(据我了解)
我们考虑过使用 credstash 等工具来帮助管理凭据。此解决方案要求 CodeBuild 和 ECS 任务实例都能够使用 AWS CLI。为了避免混用更多凭证,我们决定最好将特权角色分配给需要使用 AWS CLI 的实例。这样,CLI 可以从实例元数据
中的角色推断凭据
鉴于这些限制,我们已尝试设计一种方法来管理我们的秘密。对于每个应用程序,我们创建一个管道。使用 Cloudformation 模板,我们创建:
4 个资源:
- DynamoDB 凭据table
- KMS 凭据密钥
- ECR 回购
- CodePipeline(构建、部署等)
3 个角色:
- CodeBuildRole
对 DynamoDB 凭证的读取权限 table
使用 KMS 密钥解密权限
写入 ECR 存储库
- ECSTaskRole
对 DynamoDB 凭证的读取权限 table
使用 KMS 密钥解密权限
从 ECR 存储库读取
- 开发人员角色
对 DynamoDB 凭证的读写权限 table
使用 KMS 密钥加密和解密权限
CodePipeline 的 CodeBuild 步骤采用 CodeBuildRole 以允许它从凭证 table 中读取构建时间机密。 CodeBuild 然后构建项目并生成一个 Docker 图像,并将其推送到 ECR。最终,部署步骤使用 Cloudformation 模板和项目 public 存储库中随附的参数文件创建 ECS 服务 ECS 任务定义包括假定 ECSTaskRole 以允许任务从中读取 运行 时间机密凭据 table 并从 ECR 中提取所需的图像。
Here is a simple diagram of the AWS resources and their relationships as stated above
我们目前提出的解决方案存在以下问题:
- 角色重
- 创建角色是我们组织中的一项特权操作。并非所有尝试创建上述管道的开发人员都有权创建必要的角色
- DeveloperRole 的手动假设:
- 就目前而言,开发人员需要手动承担 DeveloperRole。我们考虑过将开发人员用户 ARN 列表作为参数传递给管道 Cloudformation 模板的想法。 Cloudformation 是否具有将角色或策略分配给指定用户的机制?
在 CodePipeline 中是否有更完善的方法来传递我们可能忽略的秘密,或者这是我们能得到的最好的方法?
在较高级别,您可以将应用程序隔离在具有精细权限的单个 AWS 帐户中(这听起来像您正在尝试做的事情)或使用多个 AWS 帐户。两者本身都没有对错,但我更倾向于使用单独的 AWS 账户而不是管理精细权限,因为你的起点是完全隔离。
三个想法:
AWS Secret ManagerAWS Secrets Manager 帮助您保护秘密以访问应用程序、服务和 IT 资源。您可以在整个生命周期内轮换、管理和检索数据库凭据、API 密钥和其他秘密。
AWS Parameter Store 可以通过精细访问保护访问密钥。这种访问可以基于 ServiceRoles。
ECS 通过此模式提供对 ServiceRole 的访问:
build:
commands:
- curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI | jq 'to_entries | [ .[] | select(.key | (contains("Expiration") or contains("RoleArn")) | not) ] | map(if .key == "AccessKeyId" then . + {"key":"AWS_ACCESS_KEY_ID"} else . end) | map(if .key == "SecretAccessKey" then . + {"key":"AWS_SECRET_ACCESS_KEY"} else . end) | map(if .key == "Token" then . + {"key":"AWS_SESSION_TOKEN"} else . end) | map("export \(.key)=\(.value)") | .[]' -r > /tmp/aws_cred_export.txt
- chmod +x /tmp/aws_cred_export.txt
- /aws_cred_export.txt && YOUR COMMAND HERE
如果您提供给 CodeBuild 任务的 ServiceRole 有权使用参数存储密钥,您就可以开始了。
狩猎愉快,希望对您有所帮助
我们正在处理为使用 AWS CodePipeline 构建并部署到 ECS 的应用程序提供构建时间和 运行 时间机密的问题。
最终,我们的愿景是为我们的每个应用程序创建一个通用管道,以实现以下目标:
- 访问完全分离
- app-a-pipeline 中的服务无法访问任何凭据或使用 app-b-pipeline 中使用的任何密钥,反之亦然
- 指定开发人员的秘密管理
- 只有负责 app-a 的开发人员可以读取和写入 app-a 的秘密
这里是手头的问题:
- 我们的一些应用程序需要访问私有存储库以在构建时解决依赖关系 例如,我们的 java 应用程序需要访问私有 Maven 存储库才能成功构建
- 我们的一些应用程序在 运行 时需要数据库访问凭据 例如,servlet 容器 运行 连接我们的应用程序需要一个 .xml 配置文件,其中包含用于查找和访问数据库的凭据
还有一些注意事项:
- 我们的代码库位于 public 存储库中。我们不想通过将秘密的明文或密文放入我们的存储库来暴露秘密
- 我们不想将 运行时间秘密烘焙到我们在 CodeBuild 中创建的 Docker 图像中,即使 ECR 访问受到限制
- ECS 资源的 Cloudformation 模板及其关联的参数文件以明文形式驻留在 public 存储库中。这消除了通过参数将 运行 时间秘密传递给 ECS Cloudformation 模板的可能性(据我了解)
我们考虑过使用 credstash 等工具来帮助管理凭据。此解决方案要求 CodeBuild 和 ECS 任务实例都能够使用 AWS CLI。为了避免混用更多凭证,我们决定最好将特权角色分配给需要使用 AWS CLI 的实例。这样,CLI 可以从实例元数据
中的角色推断凭据鉴于这些限制,我们已尝试设计一种方法来管理我们的秘密。对于每个应用程序,我们创建一个管道。使用 Cloudformation 模板,我们创建:
4 个资源:
- DynamoDB 凭据table
- KMS 凭据密钥
- ECR 回购
- CodePipeline(构建、部署等)
3 个角色:
- CodeBuildRole 对 DynamoDB 凭证的读取权限 table 使用 KMS 密钥解密权限 写入 ECR 存储库
- ECSTaskRole 对 DynamoDB 凭证的读取权限 table 使用 KMS 密钥解密权限 从 ECR 存储库读取
- 开发人员角色 对 DynamoDB 凭证的读写权限 table 使用 KMS 密钥加密和解密权限
CodePipeline 的 CodeBuild 步骤采用 CodeBuildRole 以允许它从凭证 table 中读取构建时间机密。 CodeBuild 然后构建项目并生成一个 Docker 图像,并将其推送到 ECR。最终,部署步骤使用 Cloudformation 模板和项目 public 存储库中随附的参数文件创建 ECS 服务 ECS 任务定义包括假定 ECSTaskRole 以允许任务从中读取 运行 时间机密凭据 table 并从 ECR 中提取所需的图像。
Here is a simple diagram of the AWS resources and their relationships as stated above
我们目前提出的解决方案存在以下问题:
- 角色重
- 创建角色是我们组织中的一项特权操作。并非所有尝试创建上述管道的开发人员都有权创建必要的角色
- DeveloperRole 的手动假设:
- 就目前而言,开发人员需要手动承担 DeveloperRole。我们考虑过将开发人员用户 ARN 列表作为参数传递给管道 Cloudformation 模板的想法。 Cloudformation 是否具有将角色或策略分配给指定用户的机制?
在 CodePipeline 中是否有更完善的方法来传递我们可能忽略的秘密,或者这是我们能得到的最好的方法?
在较高级别,您可以将应用程序隔离在具有精细权限的单个 AWS 帐户中(这听起来像您正在尝试做的事情)或使用多个 AWS 帐户。两者本身都没有对错,但我更倾向于使用单独的 AWS 账户而不是管理精细权限,因为你的起点是完全隔离。
三个想法:
AWS Secret ManagerAWS Secrets Manager 帮助您保护秘密以访问应用程序、服务和 IT 资源。您可以在整个生命周期内轮换、管理和检索数据库凭据、API 密钥和其他秘密。
AWS Parameter Store 可以通过精细访问保护访问密钥。这种访问可以基于 ServiceRoles。
ECS 通过此模式提供对 ServiceRole 的访问:
build:
commands:
- curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI | jq 'to_entries | [ .[] | select(.key | (contains("Expiration") or contains("RoleArn")) | not) ] | map(if .key == "AccessKeyId" then . + {"key":"AWS_ACCESS_KEY_ID"} else . end) | map(if .key == "SecretAccessKey" then . + {"key":"AWS_SECRET_ACCESS_KEY"} else . end) | map(if .key == "Token" then . + {"key":"AWS_SESSION_TOKEN"} else . end) | map("export \(.key)=\(.value)") | .[]' -r > /tmp/aws_cred_export.txt
- chmod +x /tmp/aws_cred_export.txt
- /aws_cred_export.txt && YOUR COMMAND HERE
如果您提供给 CodeBuild 任务的 ServiceRole 有权使用参数存储密钥,您就可以开始了。
狩猎愉快,希望对您有所帮助