【问题标题】:How to use SSH key in a Windows Container如何在 Windows 容器中使用 SSH 密钥
【发布时间】:2022-03-06 11:41:23
【问题描述】:

我创建了一个包含 Git 客户端的 Windows 容器,并且我能够使用 HTTP 从我们的 Bitbucket 服务器克隆和结帐。这意味着我需要为与 Git 的每笔交易提供用户名和密码。 我现在更想使用 SSH。因此,我使用 ssh-keygen 生成了一个 SSH 密钥,并将公钥添加到我在 Bitbucket 中的用户帐户中,在我的本地 PC 上,当我使用 Pageant 加载我的密钥时,我能够成功地与 Bitbucket 进行交易。

在容器中,我正在努力让它发挥作用。 我找到了一些信息here,这些信息包含在我的 Dockerfile 中——特别是命令 Set-Service、Start-Service 和 Get-Service。 这在一定程度上有效,这条线 RUN printf "${SSH_KEY_PASSPHRASE}" | ssh-add C:\Users\Jenkins\.ssh\id_rsa 无法构建 - 它无法识别 printf。我尝试用echo 替换它,但也失败了。

如果我从我的 Dockerfile 中删除这一行,我可以构建和运行这个容器;然后我尝试使用 powershell 会话进入它并尝试手动运行ssh-add C:\Users\Jenkins\.ssh\id_rsa,但我得到了响应Could not open a connection to your authentication agent. 如果我运行Get-Service ssh-agent,它会报告 ssh-agent 正在运行。

所以我的问题如下:

  1. 为什么ssh-add 命令不起作用?
  2. 如何在这个容器中添加我的 ssh 密钥?
  3. 当我让ssh-add 命令工作时,如何在 Dockerfile 中指定密码?

这是我的 Dockerfile:

# escape=`

FROM mcr.microsoft.com/windows/servercore
ARG SSH_KEY_PASSPHRASE

COPY .\files\Git-2.18.0-64-bit.exe      C:\installers\git-installer.exe
COPY .\files\Git-2.18.0-64-bit.inf      C:\installers\git-installer-script.inf
RUN powershell -Command `
  # Install Git ; `
  Start-Process -filepath C:\installers\git-installer.exe -passthru -wait -argumentlist "/LOADINF=C:\installers\git-installer-script.inf","/VERYSILENT","/NORESTART" ; `
Remove-Item C:\installers\ -Force -Recurse;

RUN powershell -Command `
  net user /add Jenkins; `
  net localgroup Administrators Jenkins /add;
USER Jenkins
RUN powershell -Command `
  mkdir ~\.ssh;

COPY .\id_rsa  C:\Users\Jenkins\.ssh\id_rsa

RUN powershell -Command `
  # Make sure you're running as an Administrator `
  Set-Service ssh-agent -StartupType Automatic; `
  Start-Service ssh-agent; `
  Get-Service ssh-agent; 

# This doesn't work and I don't know how to do this
RUN  printf "${SSH_KEY_PASSPHRASE}" | ssh-add C:\Users\Jenkins\.ssh\id_rsa

编辑 1

我现在发现,如果运行这个容器(在 dockerfile 中没有ssh-add 命令)然后使用 ssh URL 运行 git clone,它会指出无法建立 bitbucket 主机的真实性,执行你想继续连接吗?我输入“是”,然后它“将我的位存储桶主机永久添加到已知主机列表中”,然后询问密钥“c/Users/Jenkins/.ssh/id_rsa”的密码。

一旦我输入密码,它就会成功克隆回购。 这个结果让我很吃惊,并引出了一个新问题:

  • 如果我还没有添加它,它如何知道 c/Users/Jenkins/.ssh 中的 ssh 密钥?我显然在某处缺少一些理解。

编辑 2

我玩过我的 Dockerfile 并发现该行 RUN powershell -Command mkdir ~\.ssh 在某种程度上似乎很重要。 如果我删除此行并运行容器,我可以看到我的密钥存在于C:\Users\Jenkins\.ssh\ 但如果我运行ssh-add .\Users\Jenkins\.ssh\id_rsa 它会失败并显示Permissions for id_rsa are too open。 如果我包含mkdir 行,对我来说没有明显区别,但ssh-add 命令似乎工作并报告Identity added: .\Users\Jenkins\.ssh\id_rsa (<my company domain>+<my windows username@PC name>)。

如果我不手动创建 .ssh 文件夹,它似乎仍然是在 COPY 命令期间隐式创建的,但 ssh-add 失败。这是怎么回事?

接下来,我将 ssh-add 命令包含到我的 Dockerfile 中并重新构建它,可以看到密钥已添加 - 它报告 Identity added: .\Users\Jenkins\.ssh\id_rsa。

在这个阶段我无法与 Git 交互,因为路径没有设置,所以我修改了我的 Dockerfile 以通过在我安装 Git 的命令中添加以下行来设置路径;

${env:PATH} = 'C:\Git\bin;C:\Git\usr\bin;C:\Git\mingw64\bin;' + $env:PATH;
[Environment]::SetEnvironmentVariable('PATH', ${env:PATH}, [EnvironmentVariableTarget]::Machine);

现在,当我构建映像时,ssh-add 命令失败并显示“无法打开与您的身份验证代理的连接”。 我跑了Get-Service ssh-agent,它报告它正在运行。

所以不知何故,将 Git 包含在路径中导致了关于 ssh-add 命令的差异。 这里发生了什么? 我该如何解决这个问题?

我还重新创建了没有密码短语的密钥,因此在 docker 构建期间无需输入密码短语,并且我指定了 windows 的版本。

这是我更新的 Dockerfile:

# escape=`

FROM mcr.microsoft.com/windows/servercore:1903

# Install Git
COPY .\files\Git-2.18.0-64-bit.exe      C:\installers\git-installer.exe
COPY .\files\Git-2.18.0-64-bit.inf      C:\installers\git-installer-script.inf
RUN powershell -Command `
  Start-Process -filepath C:\installers\git-installer.exe -passthru -wait -argumentlist "/LOADINF=C:\installers\git-installer-script.inf","/VERYSILENT","/NORESTART" ; `
  Remove-Item C:\installers\ -Force -Recurse; `
  # Set the path to include Git folders - not listed in my original post `
  ${env:PATH} = 'C:\Git\bin;C:\Git\usr\bin;C:\Git\mingw64\bin;' + $env:PATH; `
  [Environment]::SetEnvironmentVariable('PATH', ${env:PATH}, [EnvironmentVariableTarget]::Machine);

# Create a Jenkins user with admin permissions
RUN powershell -Command `
  net user /add Jenkins; `
  net localgroup Administrators Jenkins /add;
  USER Jenkins
# The presence or absence of this mkdir command affects ssh-add for some reason
RUN powershell -Command `
  mkdir ~\.ssh;

# This key was created without a passphrase
COPY .\id_rsa  C:\Users\Jenkins\.ssh\id_rsa

RUN powershell -Command `
  # Make sure you're running as an Administrator `
  Set-Service ssh-agent -StartupType Automatic; `
  Start-Service ssh-agent; `
  Get-Service ssh-agent; `
  ssh-add .\Users\Jenkins\.ssh\id_rsa;

编辑 3

感谢我找到here 的信息,我似乎无法成功运行ssh-add 是由于未设置SSH_AUTH_SOCK 环境变量。
运行ssh-agent 提供设置此环境变量所需的数据,在Linux 中您可以运行eval $(ssh-agent),但Windows 中的powershell 无法识别eval 命令。在这个阶段,我尝试从我的最后一个 dockerfile 中注释掉 ssh-add 命令,然后在容器中我手动运行 ssh-agent 命令并使用成功的 $Env:SSH_AUTH_SOCK = "<value returned from ssh-agent>" 设置环境变量,如果我运行 Get-ChildItem Env: 我看到了列出了新的环境变量。

然后我尝试运行git clone ssh://git@mybitbucketurl/myrepo.git 报告“无法确定主机 mybitbucketurl (xx.yy.zz.aa:port) 的真实性。您确定要继续吗(是/否) ?”
我输入“是”,它“将 mybitbucketurl:port,[xx.yy.zz.aa]:port (RSA) 永久添加到已知主机列表中”,然后克隆了我的存储库。

我认为我现在已经破解了这个问题,并认为我只需要弄清楚如何在 powershell 中执行 eval 等效命令。当我在寻找有关如何执行此操作的线索时,我发现了这个link,其中的答案列出了这个命令: ssh-agent ssh-add C:\Users\<username>\.ssh\id_rsa。 我尝试在我的容器中手动运行它,它报告说添加了身份,但是当我尝试运行git clone 时,它首先将 URL 添加到已知主机列表中,然后失败并显示“致命:无法从远程读取存储库”。 运行 Get-ChildItem Env: 表明未设置 SSH_AUTH_SOCK 环境变量,所以我猜想像这样运行它是一种孤立的会话,尽管我真的不知道这个命令发生了什么。

因此,从这里看来,我需要弄清楚如何运行 ssh-agent 命令并在 powershell 中使用其结果来永久设置环境变量。 完成这项工作后,我需要弄清楚如何将我的 Git 主机 URL 添加到已知主机列表中。


编辑 4

我的问题的症结似乎是我的 docker 映像的构建时间和运行时间之间的差异,特别是我希望通过 ssh-agent 和 ssh-add 实现的目标。 如果我将图像设置为包含 ssh 密钥然后运行它,我可以手动执行以下操作(请注意,我已从 powershell 切换到 bash):

$ echo $SSH_AUTH_SOCK

$ eval $(ssh-agent)
Agent pid 2036
$ sh-add Users/Jenkins/.ssh/id_rsa
Identity added: Users/Jenkins/.ssh/id_rsa
$ echo $SSH_AUTH_SOCK
/tmp/ssh-qCM264wFqpqq/agent.1748

所以从这里我可以看到,在容器中运行时它会做我想做的事。 但是,如果我尝试在构建时从 Dockerfile 运行这些命令,事情就不会像我希望的那样工作。 经过一番思考,我怀疑eval $(ssh-agent) 命令可能会运行,但SSH_AUTH_SOCK 环境变量未保留在映像层中,并且当容器运行时,ssh-agent 将不会运行,可能需要启动它。

这样做的正确方法是什么:

  1. 我是否尝试通过启动脚本在容器启动期间运行这些命令?
  2. 有没有办法在构建时仍然执行此操作(即从 Dockerfile) - 为了实现这一点,我需要手动设置 SSH_AUTH_SOCK 环境变量,但这似乎每次运行 ssh-agent 时都不同 -这值得追求吗?

【问题讨论】:

    标签: git docker ssh


    【解决方案1】:

    非常感谢您完成所有这些工作并记录您的进度。 我也尝试了很多东西,我终于得到了一些工作。

    我添加了您可以在 .ssh 目录中找到的文件 known_hosts。 这对我有用:

    FROM mcr.microsoft.com/windows/servercore:ltsc2019
    
    RUN powershell -Command \
        mkdir C:\Users\ContainerAdministrator\.ssh
    COPY ["./id_ed25519", "./Users/ContainerAdministrator/.ssh/"]
    COPY ["./known_hosts", "./Users/ContainerAdministrator/.ssh/"]
    
    RUN powershell -Command \
        Set-Service ssh-agent -StartupType Automatic ; \
        Start-Service ssh-agent ; \
        ssh-add .\Users\ContainerAdministrator\.ssh\id_ed25519 ; \
        git clone <your repo> ; \
        Remove-Item C:\Users\ContainerAdministrator\.ssh -Force -Recurse
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-10
      • 2016-07-12
      • 2015-04-06
      • 2023-01-05
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      相关资源
      最近更新 更多