处理AWS CodePipeline中的运行时和构建时间机密

Tra*_*ler 7 credentials amazon-ecs aws-codepipeline aws-codebuild

我们正在处理为使用AWS CodePipeline构建并部署到ECS的应用程序提供构建时间和运行时机密的问题.

最终,我们的愿景是为每个应用程序创建一个通用管道,以实现以下目标:

  • 完全分离访问权限
    • app-a-pipeline中的服务无法访问任何凭据或使用app-b-pipeline中使用的任何密钥,反之亦然
  • 分配开发人员的秘密管理
    • 只有负责app-a的开发人员才能读取和写入app-a的秘密

以下是手头的问题:

  • 我们的一些应用程序需要访问私有存储库以在构建时进行依赖项解析例如,我们的Java应用程序需要访问私有maven存储库才能成功构建
  • 我们的一些应用程序在运行时需要数据库访问凭据例如,运行我们的应用程序的servlet容器需要一个包含凭据的.xml配置文件来查找和访问数据库

除了一些警告:

  • 我们的代码库位于公共存储库中.我们不希望通过在我们的存储库中放置秘密的明文或密文来暴露秘密
  • 即使ECR访问受到限制,我们也不希望将运行时机密烘焙到我们在CodeBuild中创建的Docker镜像中
  • ECS资源的Cloudformation模板及其相关参数文件以纯文本格式驻留在公共存储库中.这消除了通过参数将运行时机密传递到ECS Cloudformation模板的可能性(据我所知)

我们已经考虑使用像credstash这样的工具来帮助管理凭据.此解决方案要求CodeBuild和ECS任务实例都能够使用AWS CLI.为了避免改组更多凭据,我们认为最好将特权角色分配给需要使用AWS CLI的实例.这样,CLI就可以从实例元数据中的角色推断凭据

考虑到这些限制,我们试图设法管理我们的秘密.对于每个应用程序,我们创建一个管道.使用Cloudformation模板,我们创建:

  • 4资源:

    • DynamoDB凭据表
    • KMS凭证密钥
    • ECR回购
    • CodePipeline(构建,部署等)
  • 3个角色:

    • CodeBuildRole对DynamoDB凭证表的读访问权限使用KMS密钥解密权限写入ECR仓库
    • ECSTaskRole对DynamoDB凭证表的读访问权限使用KMS密钥解密权限从ECR仓库读取
    • DeveloperRole对DynamoDB凭据表的读写访问权限使用KMS密钥加密和解密权限

CodePipeline的CodeBuild步骤假定CodeBuildRole允许它从凭证表中读取构建时间机密.CodeBuild然后构建项目并生成一个Docker Image,它将其推送到ECR.最后,部署步骤使用Cloudformation模板和项目公共存储库中存在的附带参数文件创建ECS服务ECS任务定义包括假设ECSTaskRole允许任务从凭证表读取运行时机密并提取所需图像来自ECR.

以下是AWS资源及其关系的简单图表

我们当前提出的解决方案存在以下问题:

  • 角色沉重
    • 创建角色是我们组织中的特权行为.并非所有尝试创建上述管道的开发人员都有权创建必要的角色
  • 手动假设DeveloperRole:
    • 目前,开发人员需要手动承担DeveloperRole.我们玩弄了将开发者用户ARN列表作为参数传递给管道Cloudformation模板的想法.Cloudformation是否具有将角色或策略分配给指定用户的机制?

是否有更成熟的方法来传递我们可能忽略的CodePipeline中的秘密,或者这是我们能得到的最好的方法?

Eri*_*ord 4

三个想法:

AWS Secret Manager AWS Secrets Manager 可帮助您保护访问应用程序、服务和 IT 资源的机密。您可以在数据库凭证、API 密钥和其他机密的整个生命周期中轮换、管理和检索它们。

AWS 参数存储可以通过精细访问来保护访问密钥。此访问可以基于服务角色。

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
Run Code Online (Sandbox Code Playgroud)

如果您提供给 CodeBuild 任务的 ServiceRole 有权使用参数存储密钥,那么您应该可以开始了。

狩猎愉快,希望这有帮助