【问题标题】:Secure distribution of private keys to Docker on CoreOS在 CoreOS 上将私钥安全分发到 Docker
【发布时间】:2015-04-25 17:55:25
【问题描述】:

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

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

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

问题是,我到底如何才能将钥匙安全地拿到主机上。

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

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

基本上,核心问题似乎是所有东西都有一个 REST API,我不知道有什么方法可以阻止容器访问某些网络资源。

想法?

【问题讨论】:

    标签: amazon-web-services docker coreos etcd


    【解决方案1】:

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

    1. 生成公钥/私钥对
    2. 将私钥放入用于自动缩放组的 AMI
    3. 使用公钥加密引导脚本,包括秘密
    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
    

    要加密,请使用带有 smime 的 openssl 来解决 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,因此脚本及其加密数据必须小于此值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-31
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-16
      相关资源
      最近更新 更多