Docker,如何处理 ssh 密钥、known_hosts 和 authorized_keys

Posted

技术标签:

【中文标题】Docker,如何处理 ssh 密钥、known_hosts 和 authorized_keys【英文标题】:Docker, how to deal with ssh keys, known_hosts and authorized_keys 【发布时间】:2017-03-21 01:04:06 【问题描述】:

在 docker 中,当容器必须与外部系统通信时,如何根据配置 known_hosts、authorized_keys 和 ssh 连接的要求进行范围?

例如,我正在运行 jenkins 容器并尝试在作业中从 github 签出项目,但连接失败并出现错误 host key verification failed

这可以通过登录容器来解决,手动连接到 github 并在出现提示时信任主机密钥。然而,这不是正确的解决方案,因为一切都需要 100% 自动化(我正在使用 ansible 和 docker 构建 CI 管道)。另一个(笨拙的)解决方案是为正在运行的容器提供 ansible,但这会使事情变得混乱且难以维护。 Jenkins 容器甚至没有 ssh 守护进程,我不确定如何从其他主机 ssh 进入容器。第三种选择是使用我自己的 Dockerfile 扩展 jenkins 映像,其中配置了 ssh,但这将是硬编码并将容器锁定到这个特定环境。

那么,使用 docker 管理(和自动化)与外部系统的连接的正确方法是什么?

【问题讨论】:

【参考方案1】:

有个小技巧但是git版本应该>2.3

export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
git clone git@gitlab.com:some/another/repo.git

或者干脆

GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" git clone git@...

您甚至可以像这样指向私钥文件路径:

GIT_SSH_COMMAND="ssh -i /path/to/private_key_file -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" git clone git@...

【讨论】:

【参考方案2】:

如果一切都在 Dockerfile 中完成,那就很容易了。 在我的 Dockerfile 中:

ARG PRIVATE_SSH_KEY

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan example.com > /root/.ssh/known_hosts && \
    # Add the keys and set permissions
    echo "$PRIVATE_SSH_KEY" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa

...do stuff with private key

# Remove SSH keys
RUN rm -rf /root/.ssh/

您显然需要将私钥作为参数传递给建筑物(docker-compose build 或 docker build)。

【讨论】:

在单独的步骤中删除密钥可确保它不会真正被删除。抓住第一层仍然可以使用它。一步到位,确保文件真正被删除。 私钥可以使用docker buildkit内置的new secrets management。这样可以确保私钥不会出现在最终图像中。【参考方案3】:

一种解决方案是使用以下选项将主机的 ssh 密钥挂载到 docker 中:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

这非常适合 git。

【讨论】:

【参考方案4】:

试试这个: 登录主机,然后:

sudo mkdir /var/jenkins_home/.ssh/
sudo ssh-keyscan -t rsa github.com >> /var/jenkins_home/.ssh/known_hosts

Jenkins 容器将 home 位置设置为持久化地图,因此,在主机系统中运行它会生成所需的结果。

【讨论】:

【参考方案5】:

要信任 github.com 主机,您可以在启动或构建容器时发出此命令:

 ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

这会将 github 公钥添加到您已知的主机文件中。

【讨论】:

这似乎是可行的选择,可以在从 jenkins 容器派生的 Dockerfile 中运行。但是是否可以运行官方的詹金斯容器并在启动容器时注入这些主机密钥,并带有一些环境变量或其他东西?如果没有,那么我需要为 CI 环境构建自定义 jenkins 容器。 安全性怎么样?如果每次构建映像时都获取 ssh 凭据,则可能会遭受中间人攻击。 我收到这个/root/.ssh/known_hosts: Read-only file system 知道为什么吗?谢谢【参考方案6】:

我就是这样做的,但不确定你是否会喜欢这个解决方案。我有一个私人 git 存储库,其中包含授权密钥和一组公钥。然后,我使用 ansible 克隆这个存储库并替换 authorized_keys:

- git: repo=my_repo dest=my_local_folder force=yes accept_hostkey=yes

- shell: "cp my_local_folder/authorized_keys ~/.ssh/"

使用 accept_hostkey 是让我真正实现流程自动化的原因(当然,我相信来源)。

【讨论】:

以上是关于Docker,如何处理 ssh 密钥、known_hosts 和 authorized_keys的主要内容,如果未能解决你的问题,请参考以下文章

当我用尽 bigint 生成的密钥时会发生啥?如何处理?

当我用尽 bigint 生成的密钥时会发生啥?如何处理?

SSH网上商城项目实战24Struts2中如何处理多个Model请求

PHP如何处理三重加密的32字节密钥

PHP如何处理三重加密的32字节密钥

如何处理相同的哈希与相同的密钥?