在 GitLab CI/CD 中使用 SSH 密钥
目前没有在构建环境(GitLab Runner 运行的地方)中管理 SSH 密钥的内置支持。
在以下情况下使用 SSH 密钥:
- 检出内部子模块
- 使用包管理器(例如 Bundler)下载私有包
- 将您的应用程序部署到您自己的服务器,或者例如 Heroku
- 从构建环境到远程服务器执行 SSH 命令
- 将文件从构建环境 rsync 到远程服务器
对于实现上述任何一项,您很可能需要一个 SSH 密钥。
最广泛支持的方法是,通过扩展您的.gitlab-ci.yml
将一个 SSH 密钥注入你的构建环境,这是一个适用于任何类型的 executor(例如 Docker 或 shell)的解决方案。
工作原理
- 在本地创建一个新的 SSH 密钥对
ssh-keygen
。 - 将私钥作为变量添加到您的项目中。
- 在作业期间运行
ssh-agent
来加载私钥。 - 如果您正在访问私有仓库,将公钥复制到您想要访问的服务器(通常在
~/.ssh/authorized_keys
中)或将其添加为部署密钥。
在以下示例中,ssh-add -
命令不会在作业日志中显示 $SSH_PRIVATE_KEY
的值,但如果您启用 debug logging,它可能会暴露。您可能还想检查流水线的可见性。
使用 Docker executor 时的 SSH 密钥
当您的 CI/CD 作业在 Docker 容器内运行(意味着包含环境),并且您希望将代码部署在私有服务器中时,您需要一种访问它的方法。在这种情况下,您可以使用 SSH 密钥对。
-
您首先必须创建一个 SSH 密钥对。有关更多信息,请参阅生成 SSH 密钥。不要向 SSH 密钥添加密码,否则
before_script
会提示输入。 -
创建一个新的 CI/CD 变量。输入名称
SSH_PRIVATE_KEY
作为 Key,然后在 Value 字段中粘贴您之前创建的私钥的内容。 -
使用
before_script
操作修改你的.gitlab-ci.yml
。在以下示例中,假设是基于 Debian 的镜像。根据您的需要编辑:before_script: ## ## Install ssh-agent if not already installed, it is required by Docker. ## (change apt-get to yum if you use an RPM-based image) ## - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )' ## ## Run ssh-agent (inside the build environment) ## - eval $(ssh-agent -s) ## ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store ## We're using tr to fix line endings which makes ed25519 keys work ## without extra base64 encoding. ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556 ## - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - ## ## Create the SSH directory and give it the right permissions ## - mkdir -p ~/.ssh - chmod 700 ~/.ssh ## ## Optionally, if you will be using any Git commands, set the user name and ## and email. ## # - git config --global user.email "user@example.com" # - git config --global user.name "User name"
before_script
可以全局设置或按作业设置。 -
确保私有服务器的 SSH 主机密钥已验证。
-
作为最后一步,将您在第一步中创建的公钥添加到您希望在构建环境中访问的服务。如果您正在访问私有 GitLab 仓库,则必须将其添加为部署密钥。
您现在可以访问构建环境中的私有服务器或仓库。
使用 Shell executor 时的 SSH 密钥
如果您使用的是 Shell executor 而不是 Docker,则设置 SSH 密钥会更容易。
您可以从安装了 GitLab Runner 的机器生成 SSH 密钥,并将该密钥用于在该机器上运行的所有项目。
-
首先,登录到运行您的作业的服务器。
-
然后,从终端以
gitlab-runner
用户身份登录:sudo su - gitlab-runner
-
按照生成 SSH 密钥的说明生成 SSH 密钥对。不要向 SSH 密钥添加密码,否则
before_script
会提示输入。 -
作为最后一步,将您之前创建的公钥添加到您希望在构建环境访问的服务中。如果您正在访问私有 GitLab 仓库,则必须将其添加为部署密钥。
生成密钥后,尝试登录远程服务器接受指纹:
ssh example.com
验证 SSH 主机密钥
建议检查私有服务器自己的公钥,以确保您没有成为中间人攻击的目标。如果发生任何可疑情况,因为作业失败(当公钥不匹配时 SSH 连接失败),您会注意到。
要找出服务器的主机密钥,请从受信任的网络(理想情况下,从私有服务器本身)运行 ssh-keyscan
命令:
## Use the domain name
ssh-keyscan example.com
## Or use an IP
ssh-keyscan 1.2.3.4
创建一个新的 CI/CD 变量,将 SSH_KNOWN_HOSTS
作为 “Key”,并添加 ssh-keyscan
的输出作为 “Value”。
如果必须连接多台服务器,则所有服务器主机密钥必须收集在变量的 Value 中,每行一个密钥。
.gitlab-ci.yml
中直接使用变量而不是 ssh-keyscan
,如果主机域名因某种原因发生变化,您不必更改 .gitlab-ci.yml
。此外,这些值是由您预定义的,这意味着如果主机密钥突然更改,CI/CD 作业不会失败,此时是服务器或网络存在问题。现在创建了 SSH_KNOWN_HOSTS
变量,除了上面的 .gitlab-ci.yml
的内容之外,还必须添加:
before_script:
##
## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
## following two lines.
##
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
##
## Alternatively, use ssh-keyscan to scan the keys of your private server.
## Replace example.com with your private server's domain name. Repeat that
## command if you have more than one server to connect to.
##
# - ssh-keyscan example.com >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
##
## You can optionally disable host key checking. Be aware that by adding that
## you are susceptible to man-in-the-middle attacks.
## WARNING: Use this only with the Docker executor, if you use it with shell
## you will overwrite your user's SSH config.
##
# - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'