在Windows容器中如何使用SSH密钥

3
我创建了一个包含Git客户端的Windows容器,可以使用HTTP从我们的Bitbucket服务器克隆和检出。这意味着我需要为每个Git事务提供用户名和密码。 现在我希望改用SSH。因此,我使用ssh-keygen生成了一个SSH密钥,并将公钥添加到我的Bitbucket用户帐户中。在我的本地PC上,我能够成功地与Bitbucket交互,因为我使用Pageant加载了我的密钥。
但是在容器内部,我无法使其正常工作。我在这里找到了一些信息(链接),并将其包含在我的Dockerfile中,具体来说是Set-Service、Start-Service和Get-Service命令。这有效,但是这行代码无法构建——它无法识别printf。我尝试用echo替换它,但也失败了。
如果我从Dockerfile中删除此行,则可以构建和运行此容器;然后我尝试使用powershell会话进入其中,并尝试手动运行ssh-add C:\Users\Jenkins\.ssh\id_rsa,但我收到响应无法打开连接到您的认证代理。 如果我运行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主机的真实性,是否要继续连接?我输入“yes”,然后它会在请求'c/Users/Jenkins/.ssh/id_rsa'密钥的密码之前,"将我的bit bucket主机永久地添加到已知主机列表中"。

一旦我输入密钥密码,它就可以成功克隆存储库。 这个结果让我很惊讶,并产生了一个新问题:

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

编辑 2

我尝试修改我的Dockerfile,并发现以下行:RUN powershell -Command mkdir ~\.ssh在某种程度上似乎很重要。如果我删除此行并运行该容器,我可以看到我的密钥存在于C:\Users\Jenkins\.ssh\中,但是如果我运行ssh-add .\Users\Jenkins\.ssh\id_rsa,则会失败并出现权限过大的错误。

如果我包含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 build期间不需要输入口令,并指定了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

感谢我在这里找到的信息,似乎不能成功运行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,报告说:"the authenticity of host mybitbucketurl (xx.yy.zz.aa:port) can't be established. Are you sure you want to continue (yes/no)?"
我输入了"yes"并且它"Permanently added mybitbucketurl:port,[xx.yy.zz.aa]:port (RSA) to the list of known hosts",然后克隆了我的仓库。

我想现在我已经解决了这个问题,只需要找出如何在powershell中执行eval命令的等效命令。当我在寻找如何做到这一点时,我发现了这个链接,其中有一个答案列出了这个命令:ssh-agent ssh-add C:\Users\<username>\.ssh\id_rsa。 我尝试在我的容器中手动运行这个命令,它报告说已添加身份验证信息,但当我尝试运行git clone时,它首先将URL添加到已知主机列表中,然后失败并显示"fatal: could not read from remote repository"。 运行Get-ChildItem Env:显示SSH_AUTH_SOCK环境变量未设置,因此我猜像这样运行是一种隔离的会话,虽然我不知道这个命令正在发生什么。

因此,从这里看来,我需要找出如何在powershell中运行ssh-agent命令并永久设置环境变量后使用它的结果。 一旦我解决了这个问题,我需要找出如何将我的Git主机URL添加到已知主机列表中。


编辑 4

我的问题的关键似乎是我的 Docker 镜像的构建时间和运行时间之间的差异,特别是我希望通过 ssh-agentssh-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时似乎不同 - 追求这个值得吗?
1个回答

2
非常感谢您完成所有工作并记录进展。 我也在我的这边尝试了很多方法,最终让它正常工作了。
我添加了一个名为known_hosts的文件,你可以在.ssh目录中找到它。 这对我有用:
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接