在 GitLab CI/CD 中使用 SSH 密钥
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
GitLab 在构建环境(GitLab Runner 运行的环境)中没有内置的 SSH 密钥管理支持。
当您需要以下操作时,请使用 SSH 密钥:
- 检出内部子模块。
- 使用包管理器下载私有包。例如 Bundler。
- 将应用程序部署到您自己的服务器或 Heroku 等平台。
- 从构建环境执行 SSH 命令到远程服务器。
- 将文件从构建环境同步到远程服务器。
最广泛支持的方法是通过扩展 .gitlab-ci.yml 将 SSH 密钥注入到构建环境中,这是一种适用于任何类型 executor(如 Docker 或 shell)的解决方案。
创建和使用 SSH 密钥
要在 GitLab CI/CD 中创建和使用 SSH 密钥:
- 使用
ssh-keygen在本地 创建新的 SSH 密钥对。 - 将私钥作为 文件类型 CI/CD 变量 添加到您的项目中。变量值必须以换行符(
LF字符)结尾。要添加换行符,在保存 SSH 密钥到 CI/CD 设置之前,在最后一行末尾按 Enter 或 Return。 - 在作业中运行
ssh-agent,它会加载私钥。 - 将公钥复制到您要访问的服务器上(通常在
~/.ssh/authorized_keys中)。 如果您要访问私有 GitLab 仓库,还需要将公钥添加为 部署密钥。
在以下示例中,ssh-add - 命令不会在作业日志中显示 $SSH_PRIVATE_KEY 的值,但如果您启用了 调试日志,它可能会被暴露。您可能还想检查 流水线的可见性。
使用 Docker executor 时的 SSH 密钥
当您的 CI/CD 作业在 Docker 容器内运行(意味着环境是隔离的)并且您想要将代码部署到私有服务器时,您需要一种访问方式。在这种情况下,您可以使用 SSH 密钥对。
-
您首先必须创建一个 SSH 密钥对。更多信息请遵循 生成 SSH 密钥 的说明。 不要 为 SSH 密钥添加密码短语,否则
before_script会提示输入密码。 -
创建一个新的 文件类型 CI/CD 变量。
- 在 Key 字段中,输入
SSH_PRIVATE_KEY。 - 在 Value 字段中,粘贴您之前创建的密钥对中的私钥内容。 确保文件以换行符结尾。要添加换行符,在保存更改之前,在 SSH 密钥的最后一行末尾按 Enter 或 Return。
- 在 Key 字段中,输入
-
使用
before_script操作修改您的.gitlab-ci.yml。在以下示例中,假设使用基于 Debian 的镜像。根据需要编辑:before_script: ## ## 如果尚未安装 ssh-agent,请安装它,Docker 需要它。 ##(如果您使用基于 RPM 的镜像,请将 apt-get 更改为 yum) ## - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )' ## ## 在构建环境中运行 ssh-agent ## - eval $(ssh-agent -s) ## ## 给予正确的权限,否则 ssh-add 将拒绝添加文件 ## 将存储在 SSH_PRIVATE_KEY 文件类型 CI/CD 变量中的 SSH 密钥添加到代理存储 ## - chmod 400 "$SSH_PRIVATE_KEY" - ssh-add "$SSH_PRIVATE_KEY" ## ## 创建 SSH 目录并给予正确的权限 ## - mkdir -p ~/.ssh - chmod 700 ~/.ssh ## ## 可选,如果您将使用任何 Git 命令,设置用户名和 ## 邮箱。 ## # - git config --global user.email "[email protected]" # - 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对于访问 GitLab.com 上的仓库,您将使用 [email protected]。
验证 SSH 主机密钥
检查私有服务器自身的公钥是一个好习惯,以确保您没有成为中间人攻击的目标。如果发生任何可疑情况,您会注意到,因为作业会失败(当公钥不匹配时 SSH 连接失败)。
要查找您服务器的主机密钥,从可信网络(最好是私有服务器本身)运行 ssh-keyscan 命令:
## 使用域名
ssh-keyscan example.com
## 或使用 IP
ssh-keyscan 10.0.2.2创建一个新的 文件类型 CI/CD 变量,将 SSH_KNOWN_HOSTS 作为 “Key”,将 ssh-keyscan 的输出作为 “Value”。确保文件以换行符结尾。要添加换行符,在保存更改之前,在 SSH 密钥的最后一行末尾按 Enter 或 Return。
如果您必须连接到多个服务器,所有服务器主机密钥必须收集在变量的 Value 中,每行一个密钥。
使用文件类型 CI/CD 变量而不是直接在 .gitlab-ci.yml 中使用 ssh-keyscan,好处是如果主机域名因某种原因更改,您不必更改 .gitlab-ci.yml。此外,值是由您预定义的,这意味着如果主机密钥突然更改,CI/CD 作业不会失败,所以服务器或网络有问题。
现在 SSH_KNOWN_HOSTS 变量已创建,除了 .gitlab-ci.yml 的内容,您还必须添加:
before_script:
##
## 假设您创建了 SSH_KNOWN_HOSTS 文件类型 CI/CD 变量,取消注释以下两行。
##
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
##
## 或者,使用 ssh-keyscan 扫描您私有服务器的密钥。
## 将 example.com 替换为您的私有服务器域名。如果您有多个要连接的服务器,请重复该命令。
## 包含 -t 标志来指定密钥类型。
##
# - ssh-keyscan -t rsa,ed25519 example.com >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
##
## 您可以选择禁用主机密钥检查。请注意,通过添加此选项,您容易受到中间人攻击。
## 警告:仅与 Docker executor 一起使用,如果您与 shell 一起使用,您将覆盖用户的 SSH 配置。
##
# - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'不使用文件类型 CI/CD 变量使用 SSH 密钥
如果您不想使用文件类型 CI/CD 变量,SSH 项目示例 展示了另一种方法。此方法使用常规 CI/CD 变量而不是之前推荐的文件类型变量。
故障排除
Error loading key "/builds/path/SSH_PRIVATE_KEY": error in libcrypto 消息
如果 SSH 密钥有格式错误,可能会返回此消息。
当将 SSH 密钥保存为 文件类型 CI/CD 变量 时,值必须以换行符(LF 字符)结尾。要添加换行符,在保存变量之前,在 SSH 密钥的 -----END OPENSSH PRIVATE KEY----- 行末尾按 Enter 或 Return。