和极狐GitLab CI/CD 一起使用 SSH keys

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: JihuLab.com, 私有化部署

极狐GitLab 没有内置支持在构建环境中管理 SSH 密钥(即极狐GitLab Runner 运行的地方)。

当您想要:

  1. 检出内部子模块。
  2. 使用软件包管理器下载私有软件包。例如,Bundler。
  3. 将应用程序部署到您自己的服务器,或者例如 Heroku。
  4. 从构建环境对远程服务器执行 SSH 命令。
  5. 从构建环境使用 Rsync 同步文件到远程服务器。

如果上述任何一项引起您的注意,那么您很可能需要一个 SSH 密钥。

最广泛支持的方法是通过扩展您的 .gitlab-ci.yml 来注入 SSH 密钥到构建环境中,这是一个适用于任何类型执行器(例如 Docker 或 shell)的解决方案。

创建和使用 SSH 密钥#

在极狐GitLab CI/CD 中创建和使用 SSH 密钥:

  1. 使用 ssh-keygen 在本地创建一个新的 SSH 密钥对
  2. 将私钥作为文件类型 CI/CD 变量添加到您的项目中。变量值必须以换行符(LF 字符)结尾。要添加换行符,请在 SSH 密钥最后一行的末尾按 EnterReturn,然后在 CI/CD 设置中保存。
  3. 在作业中运行 ssh-agent,加载私钥。
  4. 将公钥复制到您想访问的服务器上(通常在 ~/.ssh/authorized_keys 中)。如果您访问的是私有极狐GitLab 仓库,您还需要将公钥添加为部署密钥

在下面的示例中,ssh-add - 命令不会在作业日志中显示 $SSH_PRIVATE_KEY 的值,尽管如果启用调试日志记录,它可能会被暴露。您可能还想检查流水线的可见性

使用 Docker 执行器时的 SSH 密钥#

当您的 CI/CD 作业在 Docker 容器中运行(意味着环境是隔离的)并且您想要在私有服务器上部署代码时,您需要一种方式来访问它。在这种情况下,您可以使用 SSH 密钥对。

  1. 您首先必须创建一个 SSH 密钥对。有关更多信息,请按照说明生成 SSH 密钥不要给 SSH 密钥添加密码,或者 before_script 会提示输入密码。

  2. 创建一个新的文件类型 CI/CD 变量

    • Key 字段中输入 SSH_PRIVATE_KEY
    • Value 字段中粘贴您之前创建的密钥对中的 私钥 内容。确保文件以换行符结尾。要添加换行符,请在 SSH 密钥最后一行的末尾按 EnterReturn 后保存更改。
  3. 使用 before_script 动作修改您的 .gitlab-ci.yml。在下面的示例中,假设使用的是基于 Debian 的镜像。根据需要进行编辑:

    yaml
    1before_script: 2 ## 3 ## 如果未安装 ssh-agent,则安装它,Docker 需要它。 4 ## (如果您使用的是基于 RPM 的镜像,请将 apt-get 更改为 yum) 5 ## 6 - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )' 7 8 ## 9 ## 在构建环境中运行 ssh-agent 10 ## 11 - eval $(ssh-agent -s) 12 13 ## 14 ## 给予正确的权限,否则 ssh-add 将拒绝添加文件 15 ## 将存储在 SSH_PRIVATE_KEY 文件类型 CI/CD 变量中的 SSH 密钥添加到代理存储中 16 ## 17 - chmod 400 "$SSH_PRIVATE_KEY" 18 - ssh-add "$SSH_PRIVATE_KEY" 19 20 ## 21 ## 创建 SSH 目录并给予正确的权限 22 ## 23 - mkdir -p ~/.ssh 24 - chmod 700 ~/.ssh 25 26 ## 27 ## 可选地,如果您将使用任何 Git 命令,请设置用户名和电子邮件。 28 ## 29 # - git config --global user.email "user@example.com" 30 # - git config --global user.name "User name"

    before_script 可以设置为默认或每个作业。

  4. 确保私有服务器的 SSH 主机密钥已验证

  5. 最后一步,将您在第一步中创建的 公钥 添加到您希望从构建环境内部访问的服务中。如果您访问的是私有极狐GitLab 仓库,您必须将其添加为部署密钥

完成了!您现在可以在构建环境中访问私有服务器或仓库。

使用 Shell 执行器时的 SSH 密钥#

如果您使用的是 Shell 执行器而不是 Docker,则更容易设置 SSH 密钥。

您可以从安装极狐GitLab Runner 的机器生成 SSH 密钥,并将该密钥用于在该机器上运行的所有项目。

  1. 首先,登录运行您的作业的服务器。

  2. 然后,从终端以 gitlab-runner 用户身份登录:

    shell
    sudo su - gitlab-runner
  3. 按照说明生成 SSH 密钥生成 SSH 密钥对。不要给 SSH 密钥添加密码,否则 before_script 会提示输入密码。

  4. 最后一步,将您之前创建的 公钥 添加到您希望从构建环境内部访问的服务中。如果您访问的是私有极狐GitLab 仓库,您必须将其添加为部署密钥

生成密钥后,尝试登录到远程服务器以接受指纹:

shell
ssh example.com

要访问 JihuLab.com 上的仓库,您将使用 git@gitlab.com

验证 SSH 主机密钥#

检查私有服务器自己的公钥是一个好习惯,以确保您没有被中间人攻击。如果发生任何可疑情况,您会注意到,因为作业会失败(当公钥不匹配时,SSH 连接会失败)。

要找出服务器的主机密钥,请从可信网络(理想情况下,从私有服务器本身)运行 ssh-keyscan 命令:

shell
## 使用域名 ssh-keyscan example.com ## 或者使用 IP ssh-keyscan 10.0.2.2

创建一个新的文件类型 CI/CD 变量,将 SSH_KNOWN_HOSTS 作为 "Key",并将 ssh-keyscan 的输出作为 "Value" 添加。确保文件以换行符结尾。要添加换行符,请在 SSH 密钥最后一行的末尾按 EnterReturn 后保存更改。

如果您必须连接到多个服务器,则所有服务器主机密钥必须收集在变量的 Value 中,每行一个密钥。

通过使用文件类型 CI/CD 变量而不是直接在 `.gitlab-ci.yml` 中使用 `ssh-keyscan`,其好处在于如果主机域名由于某种原因发生更改,您不必更改 `.gitlab-ci.yml`。此外,值是您预定义的,这意味着如果主机密钥突然更改,CI/CD 作业不会失败,因此服务器或网络存在问题。

现在已经创建了 SSH_KNOWN_HOSTS 变量,除了上面的 .gitlab-ci.yml 的内容,您必须添加:

yaml
1before_script: 2 ## 3 ## 假设您创建了 SSH_KNOWN_HOSTS 文件类型 CI/CD 变量,取消注释下面的两行。 4 ## 5 - cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts 6 - chmod 644 ~/.ssh/known_hosts 7 8 ## 9 ## 或者,使用 ssh-keyscan 扫描您的私有服务器的密钥。 10 ## 将 example.com 替换为您的私有服务器的域名。如果您有多个服务器要连接,请重复该命令。包含 -t 标志以指定密钥类型。 11 ## 12 # - ssh-keyscan -t rsa,ed25519 example.com >> ~/.ssh/known_hosts 13 # - chmod 644 ~/.ssh/known_hosts 14 15 ## 16 ## 您可以选择禁用主机密钥检查。请注意,通过添加该选项,您容易受到中间人攻击。 17 ## WARNING: 仅在 Docker 执行器中使用此选项,如果在 shell 中使用它,您将覆盖用户的 SSH 配置。 18 ## 19 # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'

故障排查#

Error loading key "/builds/path/SSH_PRIVATE_KEY": error in libcrypto 消息#

如果 SSH 密钥格式错误,则可能返回此消息。

将 SSH 密钥保存为文件类型 CI/CD 变量时,值必须以换行符(LF 字符)结尾。要添加换行符,请在 -----END OPENSSH PRIVATE KEY----- 行的末尾按 EnterReturn 后保存变量。