在AWS CodePipeline

时间:2017-03-27 15:06:08

标签: 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 repo
    • 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。

Here is a simple diagram of the AWS resources and their relationships as stated above

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

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

是否有一种更为完善的方式来传递我们可能忽略的CodePipeline中的秘密,或者这是我们能够获得的最佳方式?

2 个答案:

答案 0 :(得分:3)

三个想法:

AWS Secret Manager AWS 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有权使用参数存储键,那么您应该很高兴。

快乐狩猎和希望这有助于

答案 1 :(得分:0)

在较高级别,您可以使用细化权限(这听起来像您尝试做的那样)或使用多个AWS账户来隔离单个AWS账户中的应用程序。这本身既不对或错,但我倾向于支持单独的AWS账户而不是管理细化权限,因为您的起始位置是完全隔离的。