7

我们正在处理为使用 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 映像,并将其推送到 ECR。最终,部署步骤使用 Cloudformation 模板和项目公共存储库中存在的随附参数文件创建 ECS 服务 ECS 任务定义包括假设 ECSTaskRole 以允许任务从凭证表中读取运行时机密并提取所需的图像来自 ECR。

这是 AWS 资源及其关系的简单图表,如上所述

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

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

有没有更完善的方法可以在 CodePipeline 中传递我们可能忽略的秘密,或者这是我们能得到的最好的方法?

4

2 回答 2

4

三个想法:

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 有权使用参数存储密钥,那么您应该可以开始了。

狩猎愉快,希望这会有所帮助

于 2017-05-16T20:29:46.607 回答
1

在较高级别上,您可以将应用程序隔离在具有精细权限的单个 AWS 账户中(这听起来像您正在尝试做的事情),也可以使用多个 AWS 账户。本身没有对错,但我倾向于使用单独的 AWS 账户而不是管理细粒度权限,因为您的起点是完全隔离的。

于 2017-04-04T17:04:40.260 回答