amazon-web-services - 将私钥安全分发到 CoreOS 上的 Docker

标签 amazon-web-services docker coreos etcd

我们开始使用 Docker/CoreOS 作为我们的基础设施。我们正在 EC2 上部署。 CoreOS 集群由自动缩放组管理,因此新主机会不断出现。另外,它们的数量很多。我正在尝试找到一种方法将 key (RSA 私有(private) key 或对称密码的共享 key )分发给所有主机,以便我可以使用它来安全地分发数据库凭证、某些服务的 AWS 访问 key 等内容。

我愿意遵守“最小特权原则”。具体来说,如果我在同一主机上运行的 2 个不同容器中有 2 个应用程序,则每个应用程序都只能访问应用程序所需的 secret 。例如,应用程序 A 可能有权访问 MySQL 凭证,应用程序 B 可能有权访问 Dynamo 的 AWS 访问 key ,但 A 无法访问 Dynamo,B 也无法访问 MySQL。

如果我在每台服务器上都有一个 secret ,那么这并不难。我可以使用像 Crypt 这样的工具从 etcd 中读取加密的配置数据,然后使用卷映射有选择地使凭据可供各个容器使用。

问题是,我到底如何才能安全地将 key 连接到主机上。

以下是我考虑过的一些事情以及它们不起作用的原因:

  • 使用 AWS 角色授予每个主机对加密 S3 存储桶的访问权限。然后,主机可以从那里读取共享 secret 。但这不起作用,因为 S3 有 REST API,Docker 不限制容器的网络访问权限,并且该角色适用于整个主机。因此,该主机上的任何容器都可以从 S3 中读取 key ,然后从 etcd(也具有不受限制的 REST API)中读取所有值并解密它们。
  • 在我的 CloudFormation 模板中,我可以有一个 key 参数。然后将其嵌入到 UserData 中并分发到所有主机。不幸的是,任何容器都可以通过元数据服务 REST API 检索 key 。
  • 使用fleet向所有主机提交全局单元,并且该单元复制 key 。但是,容器可以通过其 REST API 访问舰队并执行“fleetctl cat”来查看 key 。
  • 将 key 放入私有(private)存储库的容器中。然后可以将其作为全局单元分发到所有主机,并且该容器中的应用程序可以将 key 复制到卷安装中。但是,我假设给定私有(private)存储库的凭据,有人可以使用标准网络工具下载容器并提取 key (尽管需要付出一些努力)。接下来的问题就变成了如何安全地分发具有私有(private)存储库凭据的 .dockercfg,我认为这可以让我们回到开始的地方。

基本上,核心问题似乎是一切都有 REST API,而我不知道如何阻止容器访问某些网络资源。

想法?

最佳答案

如果您愿意将 secret 保存在 AMI 中,则可以使用您提到的 Crypt 解决方案。我实现了类似的东西,如下所示:

  1. 生成公钥/私钥对
  2. 将私钥烘焙到用于自动扩缩组的 AMI
  3. 使用公钥加密引导脚本,包括 secret
  4. 对加密的引导脚本进行 Base64 编码
  5. 将编码文本嵌入使用私钥解密的包装脚本中,并将其用作 AWS 启动配置的用户数据。

例如,引导脚本可能如下所示:

db="mysql://username:password@somehost:3306/somedb"
apikey="some_api_secret_key"
docker run --name "first container" -e db=$db -d MyImage MyCommand
docker run --name "second container" -e apikey=$apikey -d MyOtherImage MyOtherCommand

要加密,请使用 openssl 和 smime 来解决 rsautl 的下限。假设引导脚本位于/tmp/bootstrap.txt,它可以像这样加密和编码:

$ openssl smime --encrypt -aes256 -binary -outform D -in /tmp/bootstrap.txt /tmp/public.key | openssl base64 -e > /tmp/encrypted.b64

成为用户数据的包装器脚本可能如下所示:

#!/usr/bin/env bash -x 
exec >> /tmp/userdata.log 2>&1

cat << END > /tmp/bootstrap.dat
<contents of /tmp/encrypted.b64>
END
decrypted_blob=$(cat /tmp/bootstrap.dat | openssl base64 -d | openssl smime -decrypt -inform -D binary -inkey /path/to/secret.key
eval "${decrypted_blob}"
rm /tmp/bootstrap.dat

现在,如果容器访问 EC2 元数据,它们将看到用户数据脚本,但它只有加密的 blob。私钥位于主机上,容器无权访问该主机(理论上)。

另请注意,用户数据大小限制为 16KB,因此脚本及其加密数据必须小于该限制。

关于amazon-web-services - 将私钥安全分发到 CoreOS 上的 Docker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28690219/

相关文章:

docker - 容器之间未创建链接

docker - 当我们拥有 WebDeploy 时,为什么要为 .NET Web 应用程序使用 Docker?

Docker-compose --isolation=hyperv 标签

nginx - 如何在 CoreOS 中负载均衡服务?

docker - Docker容器在CoreOS中消失了一段时间

amazon-web-services - 如何获取 AWS JavaScript SDK 调用的响应 header ?

json - 同一安全组的 CidrIp json 模板

amazon-web-services - 您如何在 serverless.yml 文件中引用函数 (Lambda) 的函数 ARN?

amazon-web-services - 在 lambda 中使用 aws-sdk? (AWS.ApiGatewayManagementApi 不是 Response 的构造函数)

docker - 从 docker 容器中结构化日志记录到日志