57

我设置了 GitLab 和 GitLab CI 来托管和测试我的一些私人存储库。对于这个系统下的作曲家模块,我设置了 Satis 来解析我的私有包。

显然,这些私有包需要一个 ssh 密钥来克隆它们,而我在终端中有这个工作 - 我可以运行 composer install 并获取这些包,只要我ssh-add在 shell 中添加了密钥。

但是,当在 GitLab CI 中运行我的测试时,如果项目具有这些依赖项中的任何一个,则测试将无法完成,因为我的 GitLab 实例需要身份验证才能获取 deps(显然),并且测试失败并显示Host key verification failed.

我的问题是如何设置它,以便当运行者运行测试时,它可以在没有密码的情况下向 gitlab 进行身份验证?我已经尝试在我的 runners 文件夹中放置一个无密码的 ssh-key ~/.ssh,但是构建甚至不会添加密钥,“eval ssh-agent -s”后跟 ssh-add 似乎无法说明代理没有运行......

4

11 回答 11

51

另请参阅其他解决方案:


这里有一个完整的 SSH 密钥方法:

一般设计

  • 生成一对 SSH 密钥
  • 将私有变量添加为项目的安全环境变量
  • 在 GitLab-CI 上为您的测试脚本提供私有的
  • 在您的每个私有依赖项上添加公共密钥作为部署密钥

生成一对公钥和私钥 SSH

生成一对不带密码的公共和私有 SSH 密钥:

ssh-keygen -b 4096 -C "<name of your project>" -N "" -f /tmp/name_of_your_project.key

将私有 SSH 密钥添加到您的项目

您需要将密钥作为安全环境变量添加到您的项目中,如下所示:

  • 浏览https://<gitlab_host>/<group>/<project_name>/variables
  • 点击“添加变量”
  • Key用_SSH_PRIVATE_KEY
  • Value用 SSH 私钥本身填充文本字段
  • 点击“保存更改”

将私有 SSH 密钥公开给您的测试脚本

为了使您的私钥可用于您的测试脚本,您需要将以下内容添加到您的.gitlab-ci.yml文件中:

before_script:
  # install ssh-agent
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  # run ssh-agent
  - eval $(ssh-agent -s)
  # add ssh key stored in SSH_PRIVATE_KEY variable to the agent store
  - ssh-add <(echo "$SSH_PRIVATE_KEY")
  # disable host key checking (NOTE: makes you susceptible to man-in-the-middle attacks)
  # WARNING: use only in docker container, if you use it with shell you will overwrite your user's ssh config
  - mkdir -p ~/.ssh
  - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

代码片段来自 GitLab 文档

将公共 SSH 密钥作为部署密钥添加到所有私有依赖项

您需要将公共 SSH 密钥注册为所有私有依赖项的部署密钥,如下所示:

  • 浏览https://<gitlab_host>/<group>/<dependency_name>/deploy_keys
  • 点击“新部署密钥”
  • Title用您的项目名称填写文本字段
  • Key用公共 SSH 密钥本身填充文本字段
  • 点击“创建部署密钥”
于 2016-07-25T14:19:27.863 回答
35

如果您不想摆弄 ssh 密钥或子模块,则可以覆盖 git 配置中的 repo 以使用作业令牌进行身份验证(in gitlab-ci.yml):

before_script:
  - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/group/repo.git".insteadOf git@gitlab.example.com:group/repo.git
于 2018-03-29T09:23:41.327 回答
26

我将其发布为答案,因为其他人并不完全清楚和/或详细的恕我直言

从 GitLab 8.12+ 开始,假设子模块 repo 与请求它的服务器位于同一服务器中,您现在可以:

  1. 像往常一样使用 git 子模块设置 repo ( git submodule add git@somewhere:folder/mysubmodule.git)

  2. 修改你的.gitmodules文件如下

     [submodule "mysubmodule"]
       path = mysubmodule
       url = ../../group/mysubmodule.git
    

    where../../group/mysubmodule.git是从您的存储库到子模块的相对路径。

  3. 将以下行添加到gitlab-ci.yml

     variables:
       GIT_SUBMODULE_STRATEGY: recursive
    

    指示运行器在构建之前获取所有子模块。

警告:如果您的跑步者似乎忽略了该GIT_SUBMODULE_STRATEGY指令,您可能应该考虑更新它

(来源:https ://docs.gitlab.com/ce/ci/git_submodules.html )

于 2017-02-14T11:01:34.637 回答
20

当前接受的答案将特定于 Gitlab 的要求嵌入到我的.gitmodules文件中。这会强制本地开发使用特定的目录布局,并且会使迁移到另一个版本控制平台变得复杂。

相反,我遵循了Juddling 回答中的建议。这是一个更完整的答案。

我的.gitmodules文件有以下内容:

[submodule "myproject"]
    url = git@git.myhost.com:mygroup/myproject.git

在我的gitlab-ci.yml我有以下内容:

build:
  stage: build
  before_script:
    - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@git.myhost.com/".insteadOf "git@git.myhost.com:"
    - git submodule sync && git submodule update --init

尾随/和在行:中很关键git config,因为我们正在从 SSH 身份验证映射到 HTTPS。这让我因“非法端口号”错误而绊倒了一段时间。

我喜欢这个解决方案,因为它将特定于 Gitlab 的要求嵌入到特定于 Gitlab 的文件中,而其他所有文件都忽略了该文件。

于 2018-12-13T09:20:49.523 回答
7

我使用部署令牌来解决这个问题,因为为测试运行器设置 SSH 密钥似乎有点冗长。

git clone http://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git

部署令牌是每个项目的,并且是只读的。

于 2018-07-08T00:24:22.020 回答
3

在不更改 git 存储库结构的情况下解决此问题的一种方法是执行以下步骤:

1. 获取 ssh 主机密钥

获取您正在运行的服务器的 ssh 主机密钥。对于gitlab.com

  1. ssh-keyscan gitlab.com > known_hosts
  2. 检查是否与此处ssh-keygen -lf known_hosts报告的指纹一致 。
  3. 复制 的内容并将其粘贴到存储库known_hosts上调用的变量上。SSH_KNOWN_HOSTS

这一步只需要一次。

2.配置job使用ssh

before_script:
    - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com".insteadOf "git@gitlab.com:"
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts

"ssh://git@gitlab.com"如果您尝试这样做,则git clone git@gitlab.com:该位可能会有所不同pip install -e git+ssh://git@gitlab.com/...; 根据您的需要进行调整。

此时,您的 CI 可以使用 ssh 从另一个(私有)存储库中获取。

3.【奖励干货】

使用这个技巧来写它:

.enable_ssh: &enable_ssh |-
    git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com".insteadOf "ssh://git@gitlab.com"
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh
    echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    chmod 644 ~/.ssh/known_hosts

并在需要它的工作上启用它

test:
    stage: test
    before_script:
        - *enable_ssh
    script:
        - ...
于 2019-11-03T10:22:57.443 回答
1

我有一个场景,我必须在 3 个不同的脚本中使用我的 ssh 密钥,所以我将 ssh 密钥内容放在一个 shell 脚本中,并在其他 3 个脚本之前先调用它。这最终不起作用,我认为是由于ssh-agentshell 脚本之间没有持续存在,或者类似的东西。我最终实际上只是将私钥输出到~/.ssh/id_rsa文件中,这肯定会持续到其他脚本。

.gitlab-ci.yml

script:
    - ci/init_ssh.sh
    - git push # or whatever you need ssh for

ci/init_ssh.sh

# only run in docker:
[[ ! -e /.dockerenv ]] && exit 0

mkdir -p ~/.ssh
echo "$GITLAB_RUNNER_SSH_KEY" > ~/.ssh/id_rsa
chmod 400 ~/.ssh/id_rsa
echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > /.ssh/config

它就像一个魅力!

于 2017-06-15T21:08:55.520 回答
1
  1. 如果您的 CI 运行器在容器模型上运行,则需要使用部署密钥。文档: https ://docs.gitlab.com/ee/user/project/deploy_tokens/#git-clone-a-repository
git clone https://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git
  1. 创建您的部署令牌
  2. 在 CI 管道变量中添加您的令牌
  3. 确保您的容器具有 git 并通过 insteadOf 更改 git URL
  image: docker:latest
  before_script:
    - apk add --no-cache curl jq python3 py3-pip git
    - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.come/".insteadOf 'git@gitlab.example.come:'

替换 URL:https ://docs.gitlab.com/ee/user/project/working_with_projects.html#authenticate-git-fetches

于 2021-05-21T06:14:44.360 回答
1

如果您使用的是基于 alpine 的图像(可能是docker:latestdocker:dind),您before_script可能看起来像这样:

before_script:
    - apk add --no-cache openssh-client git
    - mkdir -p /.ssh && touch /.ssh/known_hosts
    - ssh-keyscan gitlab.com >> /.ssh/known_hosts
    - echo $SSH_KEY | base64 -d >> /.ssh/id_rsa && chmod 600 /.ssh/id_rsa
    - git clone git@git.myhost.com:mygroup/myproject.git
于 2021-05-17T19:35:24.743 回答
0

将此添加到 .gitlab-ci.yml 对我来说是诀窍。(如此处所述:https ://docs.gitlab.com/ee/user/project/new_ci_build_permissions_model.html#dependent-repositories )

before_script:
    echo -e "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc

(我尝试按照上述答案之一设置 SSH_PRIVATE_KEY ,但它不起作用)

于 2020-03-05T09:14:07.890 回答
-1

似乎终于有了一个合理的解决方案

简而言之,从 GitLab 8.12 开始,您需要做的就是.submodulesgit submodule update --init.

于 2016-11-23T10:03:24.047 回答