2015-02-24 46 views
2

我们开始使用Docker/CoreOS作为我们的基础架构。我们正在部署EC2。 CoreOS集群由一个自动扩展组管理,因此新主机进出。另外,还有很多。我试图找到一种方法将密钥(专用RSA密钥或对称密码的共享密钥)分发给所有主机,以便我可以使用它安全地分发数据库证书,某些服务的AWS访问密钥等。在CoreOS上将私钥安全分配给Docker

我想服从“最小特权原则”。具体而言,如果我在同一主机上运行的两个不同容器中有两个应用程序,则每个应用程序只能访问该应用程序所需的机密。例如,应用程序A可能有权访问MySQL凭据,应用程序B可能有权访问Dynamo的AWS Access密钥,但A无法访问Dynamo,B无法访问MySQL。

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

问题是,我是如何安全地将钥匙放到主机上的。

这里的一些事情,我考虑过,为什么他们不工作:

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

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

想法?

回答

2

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

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

例如,引导脚本可能是这样的:

db="mysql://username:[email protected]: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元数据,他们将看到userdata脚本,但它只是具有加密的blob。私钥在主机上,哪些容器无法访问(理论上)。

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