Получение GitLab CI для клонирования частных репозиториев

У меня есть GitLab и GitLab CI, настроенные для размещения и тестирования некоторых из моих частных репозиториев. Для моих модулей композитора в этой системе я настроил Satis для разрешения моих частных пакетов.

Очевидно, эти частные пакеты требуют ssh-ключа для их клонирования, и у меня это работает в терминале - я могу запустить composer install и получить эти пакеты, если у меня есть ключ, добавленный с ssh-add в оболочке.

Однако при запуске моих тестов в GitLab CI, если у проекта есть какая-либо из этих зависимостей, тесты не будут завершены, так как моему экземпляру GitLab требуется аутентификация для получения зависимостей (очевидно), и тест не сообщает Host key verification failed.

Мой вопрос: как мне это настроить, чтобы при запуске теста бегун мог пройти аутентификацию в gitlab без пароля? Я попытался поместить ssh-ключ без пароля в папку моих runners ~/.ssh, однако сборка даже не добавляет ключ, "eval ssh-agent -s", за которым следует ssh-add, похоже, не работает, говоря, что агент не работает ...


person danbroooks    schedule 05.09.2014    source источник
comment
По состоянию на 2017 год ответ с наивысшим рейтингом устарел. Ответ Марко с использованием GIT_SUBMODULE_STRATEGY правильный. Я добавил эту функцию специально, чтобы избежать беспорядка при вводе ключей SSH.   -  person Jonathon Reinhart    schedule 25.02.2017
comment
@JonathonReinhart Но разве это решение не является проблемой безопасности? Я мог бы клонировать любой частный репозиторий GitLab, если знаю относительный URL? Бегун мог заархивировать клонированный контент и отправить его по электронной почте.   -  person Paebbels    schedule 13.02.2018
comment
@Paebbels Нет, это не проблема. Начиная с GitLab 8.12, задания CI запускаются от имени пользователя, запустившего конвейер с токеном с ограниченным набором привилегий. Задание CI может получить доступ только к тем же репозиториям, что и человек, отправивший код.   -  person Jonathon Reinhart    schedule 13.02.2018


Ответы (11)


Я публикую это как ответ, так как другие не были полностью ясны и / или подробны ИМХО.

Начиная с GitLab 8.12+, предполагая, что репозиторий подмодуля находится на том же сервере, что и тот, который его запрашивал, теперь вы можете:

  1. Настройте репо с помощью подмодулей git как обычно (git submodule add git@somewhere:folder/mysubmodule.git)

  2. Измените свой .gitmodules файл следующим образом

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

    где ../../group/mysubmodule.git - относительный путь от вашего репозитория до подмодуля.

  3. Добавьте следующие строки в gitlab-ci.yml

     variables:
       GIT_SUBMODULE_STRATEGY: recursive
    

    чтобы исполнитель получил все подмодули до сборки.

Предостережение: если ваш бегун игнорирует директиву GIT_SUBMODULE_STRATEGY, вам, вероятно, следует подумать о обновить его.

(источник: https://docs.gitlab.com/ce/ci/git_submodules.html)

person Marco A.    schedule 14.02.2017
comment
Я не поддерживаю этот подход, потому что не думаю, что Gitlab должен заставлять меня настраивать подмодули определенным образом. Я предпочитаю использовать токены Gitlab и сохранять конфигурацию в .gitlab-ci.yml. - person Duncan Jones; 13.12.2018
comment
Работает ли это решение, если вы хотите запустить git submodule update --init --recursive локально? - person Gus; 04.01.2019
comment
В частности, как можно использовать этот .gitmodules и .gitlab-ci.yml файл для gitlab-runner локального запуска? - person Gus; 04.01.2019
comment
Это не работает для репозиториев на другом сервере, у которого не может быть относительного пути. - person Thomas; 21.09.2019
comment
@Gus Да, если вы запустите git submodule update --recursive --remote локально, это работает. В моем случае все мои подмодули находятся в gitlab в одной группе. - person Sourav Sarkar; 08.05.2020
comment
Похоже, это больше не работает, по крайней мере, с gitlab-runner 13.3.1. Бегун, похоже, плохо использует этот относительный путь (т. Е. Из текущего каталога, из которого выполняется команда, а не из URL-адреса репозитория). - person cglacet; 30.10.2020

Смотрите также другие решения:


Вот полное руководство с ключами 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-ключом
  • нажмите "Создать ключ развертывания"
person toch    schedule 25.07.2016
comment
@Ridermansb Спасибо за ссылку. Ответ приходит из личного документа. Я забыл происхождение фрагмента кода. Об этом стоит упомянуть. Еще раз спасибо за указание. - person toch; 28.07.2016
comment
Могу ли я использовать другое имя, кроме SSH_PRIVATE_KEY? - person becko; 05.11.2018
comment
becko, вы можете изменить имя переменной SSH_PRIVATE_KEY. Если да, обязательно обновите его везде. - person toch; 21.03.2019
comment
Предупреждение безопасности: эта документация не использует парольную фразу для закрытого ключа. - person bbaassssiiee; 23.04.2021

Если вы не хотите возиться с ключами или подмодулями ssh, вы можете переопределить репо в конфигурации git для аутентификации с помощью токена задания (в gitlab-ci.yml):

before_script:
  - git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/group/repo.git".insteadOf [email protected]:group/repo.git
person a544jh    schedule 29.03.2018
comment
Я столкнулся с проблемой - глобальная конфигурация git сохраняется на следующих заданиях моего бегуна. Это полностью нарушает CI. У вас была эта проблема? Я не могу клонировать какие-либо ресурсы из моего gitlab, потому что CI_JOB_TOKEN устарел. - person Darkowic; 17.09.2018
comment
@Darkowic Я использую Docker runner, поэтому я не сталкивался с этой проблемой. - person a544jh; 18.09.2018
comment
Я тоже. Хотя сегодня решил :) Это из-за npm ... По умолчанию npm install изменяет package-lock.json. Когда вы устанавливаете в своем CI только выборку изменений вместо клонирования, этот измененный packge-lock.json файл сохраняется между заданиями, и npm не может ничего установить ... - person Darkowic; 18.09.2018
comment
Это решение наиболее элегантное. Работает с dockerized GitLab Community Edition 11.6.4. - person vpuente; 18.01.2019
comment
Вы также можете опустить группу и репозиторий, чтобы использовать токен задания для всех репозиториев в экземпляре gitlab. См. gist.github.com/Kovrinic/ea5e7123ab5c97d451804ea222ec - person Oliver Evans; 01.03.2021

принятый в настоящее время ответ включает требования, специфичные для Gitlab, в мой .gitmodules файл. Это заставляет конкретную структуру каталогов для локальной разработки и усложняет переход на другую платформу управления версиями.

Вместо этого я последовал совету из ответа Juddling. Вот более полный ответ.

Мои .gitmodules файлы имеют следующее содержимое:

[submodule "myproject"]
    url = [email protected]: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 "[email protected]:"
    - git submodule sync && git submodule update --init

Завершающие / и : критичны в строке git config, поскольку мы сопоставляем аутентификацию SSH с HTTPS. Это на время сбило меня с толку с ошибкой «Недопустимый номер порта».

Мне нравится это решение, потому что оно включает специфичные для Gitlab требования в специфический для Gitlab файл, который игнорируется всем остальным.

person Duncan Jones    schedule 13.12.2018
comment
Чтобы уберечь кого-то от такой же глупой ошибки сопоставления с образцом, для проектов, размещенных на gitlab.com, git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/".insteadOf "[email protected]:" - person Gus; 04.01.2019
comment
@Gus, можешь опубликовать рабочий пример файла конфигурации ci? Я разместил здесь аналогичный вопрос: stackoverflow.com/questions/58040183/, но вообще не может заставить эту работу работать - person Thomas; 21.09.2019

Я использовал токены развертывания для решения этой проблемы. , так как настройка ключей SSH для тестового запуска кажется немного утомительной.

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

Токены развертывания предназначены для каждого проекта и доступны только для чтения.

person Juddling    schedule 08.07.2018

У меня был сценарий, в котором мне приходилось использовать свой ssh-ключ в 3 разных сценариях, поэтому я поместил материал ssh-ключа в один сценарий оболочки и вызвал его первым, прежде чем остальные 3 сценария. В итоге это не сработало, я думаю, из-за того, что ssh-agent не сохраняется между сценариями оболочки или что-то в этом роде. В итоге я просто вывел закрытый ключ в файл ~/.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

Работает как часы!

person user3246077    schedule 15.06.2017
comment
Привет, @ user3246077! Большое спасибо за ответ. Я обнаружил ошибку, в последней строке отсутствует символ ~ для ссылки на дом пользователя. Ты можешь починить это? - person garciparedes; 04.03.2020

Один из способов решить эту проблему без изменения структуры репозитория 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. настроить задание на использование ssh

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

Бит "ssh://[email protected]" может быть другим, если вы пытаетесь выполнить git clone [email protected]: или pip install -e git+ssh://[email protected]/...; отрегулируйте его в соответствии с вашими потребностями.

На этом этапе ваш CI может использовать ssh для выборки из другого (частного) репозитория.

3. [Bonus DRY]

Используйте этот трюк, чтобы написать его в общем виде:

.enable_ssh: &enable_ssh |-
    git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com".insteadOf "ssh://[email protected]"
    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:
        - ...
person Jorge Leitao    schedule 03.11.2019
comment
[3] работал у меня, когда мне нужно было получить частные репозитории с помощью gitlab и go get, в частности git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com".insteadOf "https://gitlab.com" (он немного изменен) - person saniales; 25.01.2020

Добавление этого в .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, как указано в одном из ответов выше, это не сработает)

person Jay    schedule 05.03.2020

Если вы используете изображение альпийских гор (возможно, docker:latest или docker: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 [email protected]:mygroup/myproject.git
person chaitan94    schedule 17.05.2021

  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, и измените URL-адрес git на вместо
  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 '[email protected]:'

для замены URL: https://docs.gitlab.com/ee/user/project/working_with_projects.html#authenticate-git-fetches

person fei yang    schedule 21.05.2021

Кажется, наконец-то появился разумный решение.

Короче говоря, с GitLab 8.12 все, что вам нужно сделать, это использовать относительные пути в .submodules, и git submodule update --init будет просто работать

person Eri Rubin    schedule 23.11.2016
comment
Это неполная версия ответа Марко А. выше. - person Karl Richter; 09.11.2017