在启动时向机密容器添加机密

时间:2019-03-29 12:45:29

标签: docker hashicorp-vault

我试图找到一些有关在启动时向机密容器添加机密(以开发人员模式运行)的最佳方法的指导。尽管不是很干净,但我想出了一种方法。因此,我正在寻找实现此目的的更好方法的一些建议。

我获取了Vault父映像,并创建了一个Shell脚本来首先调用父映像的入口点,然后添加一个循环以等待Vault出现,初始化它,向其中添加秘密。如果我此时离开脚本,则容器只是停止并退出,因此我还添加了一个循环,以在Vault正常运行时使计时器保持运行状态。

FROM vault

# Install Curl
RUN apk add --no-cache curl

# Instal jq
ADD https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 /usr/bin/jq
RUN chmod 755 /usr/bin/jq

ENV MYSQL_URL default
ENV MYSQL_USERNAME default
ENV MYSQL_PASSWORD default
ENV VAULT_DEV_ROOT_TOKEN_ID 0000

EXPOSE 8200
ADD vault-init.sh /

RUN chmod 755 vault-init.sh

ENTRYPOINT exec "./vault-init.sh"

这是上面引用的vault-init.sh。

echo "Staring Vault..."
docker-entrypoint.sh server -dev &
echo "Sleeping 10..."
sleep 10
echo "Vault Started."

echo "Exporting address"
export VAULT_ADDR="http://localhost:8200"

echo "Authenticate into Vault"
# Authenticate to Vault
vault login $VAULT_DEV_ROOT_TOKEN_ID

echo "Adding secrets to Vault..."
vault kv put secret/fruit-basket mysql.username=$MYSQL_USERNAME mysql.password=$MYSQL_PASSWORD mysql.url=$MYSQL_URL

while [ "$(curl -XGET --insecure --silent -H "X-Vault-Token: $VAULT_DEV_ROOT_TOKEN_ID" http://localhost:8200/v1/sys/health | jq '.initialized')" == "true" ] 
do
    sleep 2
done

2 个答案:

答案 0 :(得分:1)

想到三个合理的选择。大多数情况下,它们实际上并非特定于保险柜。

将数据加载到Docker外部。 docker run vault照常进行,而无需执行问题中描述的任何操作。当它真正出现时,使用vault CLI或Docker之外的应用程序代码来加载您的种子数据。 (这类似于在 application 启动过程中运行SQL迁移脚本的Web应用程序,与 database 启动过程不同。)

将数据存储在保险柜外部。保险柜具有several storage backends。实际部署Vault的更典型设置是将其存储在Consul或S3或其他地方的数据。如果这样做,则后端(实际上是用于存储数据;保管库被设计为无状态的)可以在调整保管库配置时保留数据。您仍然必须一次加载种子数据,但是它可以在重新启动后幸免。

编写您自己的init-type程序。您确实希望主容器进程成为容器正在运行的服务。在您的示例中,如果保险柜死了,您注意到的唯一原因是因为您具有手动的运行状况检查循环。如果您确实需要以这种方式运行Vault,则需要编写自己的流程来承担 init (8)的所有职责,将所有信号转发到Vault子流程,然后执行脚本执行的操作(或运行启动后脚本)。这可能需要使用C或Go这样的语言。 W.理查德·史蒂文斯(R. Richard Stevens)的 UNIX环境中的高级编程具有正确执行此操作所需的所有信息,但这是一项重大的工作。

答案 1 :(得分:0)

感谢@David的输入。我最终所做的只是有些不同。我认为这是一个更为优雅的解决方案。我创建了两个不同的保管库容器映像,一个是运行以作为保管库工作的实际保管库映像,第二个是加载机密(称为vault-secret)。在vault-secret图像中,我重写了以上的unix脚本以等待Vault出现,然后加载秘密。由于我在脚本中覆盖了父图像的ENTRYPOINT(在这种情况下为vault ,金库仅出现在名为vault的映像上,并且vault-secret容器停止并退出,因为它在加载密钥后没有任何进程在运行(很像Kubernetes作业)。这是我的新Dockerfile和unix脚本。

FROM vault

# Install Curl
RUN apk add --no-cache curl

# Instal jq
ADD https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 /usr/bin/jq
RUN chmod 755 /usr/bin/jq

ENV MYSQL_URL default
ENV MYSQL_USERNAME default
ENV MYSQL_PASSWORD default
ENV VAULT_DEV_ROOT_TOKEN_ID 0000

EXPOSE 8200
ADD vault-init.sh /

RUN chmod 755 vault-init.sh

ENTRYPOINT exec "./vault-init.sh"

上方的vault-init.sh

echo "Waiting for Vault..."
while [ "$(curl -XGET --insecure --silent -H "X-Vault-Token: $VAULT_TOKEN" $VAULT_ADDR/v1/sys/health | jq '.initialized')" != "true" ] 
do
    echo 'Vault is Initializing...'
    sleep 2
done

echo "Vault Started."

echo "Authenticate into Vault"
# Authenticate to Vault
vault login $VAULT_TOKEN

echo "Adding secrets to Vault..."
vault kv put secret/fruit-basket mysql.username=$MYSQL_USERNAME mysql.password=$MYSQL_PASSWORD mysql.url=$MYSQL_URL

在上述解决方案中,我使用vault基本映像来运行“装入机密”作业。就是这样,我可以使用Vault命令行工具加载机密。如果要用curl代替它,则可以改用Alpine甚至busybox来减少容器的占地面积。

感谢您的阅读!