使用 docker-compose 的本地 Vault

Dek*_*kim 7 docker docker-compose hashicorp-vault

我在 docker-compose 中运行 Vault 时遇到了很大的麻烦。

我的要求是:

  • 作为守护进程运行(因此当我重新启动 Mac 时也会重新启动)
  • 秘密在容器重新启动之间保留
  • 重启之间无需人为干预(开封等)
  • 使用通用令牌

我当前的 docker-compose

version: '2.3'
services:
  vault-dev:
    image: vault:1.2.1
    restart: always
    container_name: vault-dev
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: "myroot"
      VAULT_LOCAL_CONFIG: '{"backend": {"file": {"path": "/vault/file"}}, "default_lease_ttl": "168h", "max_lease_ttl": "720h"}'
    ports:
      - "8200:8200"
    volumes:
      - ./storagedc/vault/file:/vault/file
Run Code Online (Sandbox Code Playgroud)

但是,当容器重新启动时,我得到日志

==> Vault server configuration:

             Api Address: http://0.0.0.0:8200
                     Cgo: disabled
         Cluster Address: https://0.0.0.0:8201
              Listener 1: tcp (addr: "0.0.0.0:8200", cluster address: "0.0.0.0:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
               Log Level: info
                   Mlock: supported: true, enabled: false
                 Storage: file
                 Version: Vault v1.2.1

Error initializing Dev mode: Vault is already initialized
Run Code Online (Sandbox Code Playgroud)

对于这件事有什么建议吗?

Pet*_*esh 4

我将伪编码一个答案来解决指定的问题,但请注意,这是一个大规模的黑客攻击,永远不应该将其部署在生产中,因为硬编码的主密钥和单个解封密钥是非常不安全的

因此,您需要一个具有持久性的测试库服务器。

您可以完成此操作,由于保管库容器的默认行为,它将需要一些工作 - 如果您刚刚启动它,它将以开发模式容器启动,这将不允许持久性。仅通过环境变量添加持久性并不能完全解决该问题,因为它会与容器的默认启动模式冲突。

所以我们需要用一些能够完成我们想要它做的事情的东西来替换这个入口点脚本。

首先我们将脚本从容器中复制出来:

$ docker create --name vault vault:1.2.1
$ docker cp vault:/usr/local/bin/docker-entrypoint.sh .
$ docker rm vault
Run Code Online (Sandbox Code Playgroud)

为简单起见,我们将编辑该文件并使用 docker-compose 文件将其安装到容器中。我不会让它真正发挥作用——只是足以让它做我想要的事情。这里的重点是示例,而不是在生产中可用的东西。

我的自定义全部从第 98 行开始 - 首先我们启动开发模式服务器以记录解封密钥,然后我们终止开发模式服务器。

# Here's my customization:
if [ ! -f /vault/unseal/sealfile ]; then
  # start in dev mode, in the background to record the unseal key
  su-exec vault vault server \
    -dev -config=/vault/config \
    -dev-root-token-id="$VAULT_DEV_ROOT_TOKEN_ID" \
    2>&1 | tee /vault/unseal/sealfile &
  while ! grep -q 'core: vault is unsealed' /vault/unseal/sealfile; do
    sleep 1
  done
  kill %1
fi
Run Code Online (Sandbox Code Playgroud)

接下来我们检查补充配置。这是用于禁用 TLS 和绑定适当接口的额外配置的地方。

if [ -n "$VAULT_SUPPLEMENTAL_CONFIG" ]; then
  echo "$VAULT_SUPPLEMENTAL_CONFIG" > "$VAULT_CONFIG_DIR/supplemental.json"
fi
Run Code Online (Sandbox Code Playgroud)

然后我们以“发布”模式启动保管库:

if [ "$(id -u)" = '0' ]; then
  set -- su-exec vault "$@"
  "$@"&
Run Code Online (Sandbox Code Playgroud)

然后我们从 sealfile 中获取解封密钥:

  unseal=$(sed -n 's/Unseal Key: //p' /vault/unseal/sealfile)
  if [ -n "$unseal" ]; then
    while ! vault operator unseal "$unseal"; do
      sleep 1
    done
  fi
Run Code Online (Sandbox Code Playgroud)

我们只是等待进程终止:

  wait
  exit $?
fi
Run Code Online (Sandbox Code Playgroud)

github 上有完整的要点。

现在用于执行此操作的 docker-compose.yml 与您自己的略有不同:

version: '2.3'
services:
  vault-dev:
    image: vault:1.2.1
    restart: always
    container_name: vault-dev
    command: [ 'vault', 'server', '-config=/vault/config' ]
    environment:
      VAULT_DEV_ROOT_TOKEN_ID: "myroot"
      VAULT_LOCAL_CONFIG: '{"backend": {"file": {"path": "/vault/file"}}, "default_lease_ttl": "168h", "max_lease_ttl": "720h"}'
      VAULT_SUPPLEMENTAL_CONFIG: '{"ui":true, "listener": {"tcp":{"address": "0.0.0.0:8200", "tls_disable": 1}}}'
      VAULT_ADDR: "http://127.0.0.1:8200"
    ports:
      - "8200:8200"
    volumes:
      - ./vault:/vault/file
      - ./unseal:/vault/unseal
      - ./docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh
    cap_add:
      - IPC_LOCK
Run Code Online (Sandbox Code Playgroud)

command是要执行的命令。"$@"&这就是脚本更改的内容。

我已经VAULT_SUPPLEMENTAL_CONFIG为非开发运行添加了。它需要指定接口,它需要关闭tls。我添加了 ui,因此我可以使用http://127.0.0.1:8200/ui. 这是我对脚本所做的更改的一部分。

因为这都是本地的,对于我来说,出于测试目的,我安装./vault为数据目录,安装./unseal为记录解封代码的位置,安装./docker-entrypoint.sh为入口点脚本。

我可以docker-compose up这样做,它会启动一个持久保管库 - 当我尝试在服务器启动之前解封时,日志上有一些错误,但它可以工作,并且在多次docker-compose运行中持续存在。

再次强调,这完全不适合任何形式的长期使用。如果你要做这样的事情,你最好使用 docker 自己的秘密引擎。