GitLab Series 4 Оболочка GitLab

GitLab

Читатели, прочитавшие первые три выпуска анализа, связанного с GitLab (представьте, что у вас есть читатели)

Вы обнаружите, что я всегда публикую диаграмму архитектуры Gitlab. До сих пор мы объяснили «половину» процесса того, как GitLab обрабатывает запросы HTTP / HTTPS: пользовательские запросы входят из ввода HTTP / HTTPS и прибывают на GitLab-Workhorse через Nginx. Unicorn, Unicorn можно рассматривать как слой оболочки , что гарантирует, что запросы могут быть эффективно запланированы и обработаны, и ядро, которое действительно обрабатывает запросы, в основном зависит от рельсов GitLab, то есть GitLab-Ce, и «Другая половина» обработки запроса передается GitLab-CE для сделки с участием


В этом выпуске я не собираюсь знакомить с GitLab Rails, потому что этот проект слишком большой и сложный (конечно, его можно просто рассматривать как веб-приложение, которое нуждается в поддержке персистентной базы данных PostgreSQL и распределенного кеша Redis), и это можно завести еще одну.Тема введена. Более того, в этой серии мы намерены максимально полно представить функции каждого компонента GitLab (вместо представления структуры кода проектов с открытым исходным кодом и т. д.), и просто сказано, что GitLab Rails эквивалентен реальному ядру GitLab, и здесь реализована большая часть логики обработки пользовательских запросов (в будущем планируется отследить и проанализировать исходный код gitlab-ce в сочетании с некоторыми бизнес-сценариями)

О чем этот эпизод? Не забывайте, что все предыдущие выпуски касались маршрутизации http/https, а как насчет ssh?На диаграмме архитектуры первая остановка записи ssh — GitLab Shell.. В этом разделе в основном объясняются подготовительные знания для понимания того, как работает GitLab-Shell.


Когда дело доходит до Shell, мы можем думать о терминалах командной строки, таких как bash или zsh.В какой-то степени GitLab Shell также можно рассматривать как набор предопределенных команд, но дело не только в этом.

GitLab Shell - это оболочка?

Помните объяснение, опубликованное в первом выпуске перед тем, как SSH использует алгоритм симметричного шифрования для входа на сервер входа? Резюме:На самом деле весь процесс в основном использует симметричный алгоритм шифрования с открытым ключом и дешифрованием с закрытым ключом: пользователь загружает свой собственный открытый ключ SSH на удаленный сервер (удаленный сервер$HOME/.ssh/authorized_keysВ файле будет сохранен открытый ключ, загруженный пользователем, и, как правило, его можно добавить непосредственно в конец файла.) При входе в систему удаленный сервер отправляет пользователю случайную последовательность, и пользователь шифрует ее с помощью его локальный закрытый ключ SSH и отправляет его обратно на удаленный сервер.Расшифруйте открытый ключ, сохраненный заранее, в случае успеха он доказывает, что пользователю доверяют, что позволяет вам войти в систему и больше не запрашивать пароль



Итак, когда мы выполняем операцию git-over-ssh локально, можем ли мы войти в терминал bash сервера, чтобы что-то делать? Очевидно невозможно: сервер не может позволить нашим пользователям войти в терминал для выполнения всех команд, если только администратор сервера не хочет, чтобы пользовательский опытrm -rf /*Ощущение удаления библиотеки и бегства


Итак, GitLab использует функцию SSH:Укажите команду, которая будет выполняться после входа в систему через author_keys. При входе в систему ранее удаленный сервер напрямую добавляет открытый ключ пользователя к$HOME/.ssh/authorized_keysконец файла


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


Приведенный выше рисунок в основном говорит о том, что, когда мы находимся в$HOME/.ssh/authorized_keysВ конце добавьте следующий формат:

# command="./cmd ssh-rsa <my-rsa-key>"
command="/home/git/gitlab-shell/bin/gitlab-shell key-10",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa <my-rsa-key>

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

/home/git/gitlab-shell/bin/gitlab-shell key-10

Вот почему оболочка GitLab названа так, и на самом деле это весьма образно:Только позволяет выполнять GitLab Shell на сервере, другие команды оболочки, такие какrm -rf /*Пользователи шаттла не связывайтесь со мной, из них этоkey-10это/home/git/gitlab-shell/bin/gitlab-shellпараметры выполнения командыARGV, который, конечно же, представляет идентификатор ключа пользователя

Далее посмотрим/home/git/gitlab-shell/bin/gitlab-shellкод


Обратите внимание, что мы также можем использовать$SSH_ORIGINAL_COMMANDПеременная получает команду, отправленную клиентом, теперь проведите эксперимент: распечатайте/home/git/gitlab-shell/bin/gitlab-shellизwhoиoriginalПеременная

# 打印变量值
File.write("/tmp/git_original_cmd", original_cmd)
File.write("/tmp/git_who", who)

Когда я выполняю отдельно локальноgit push | git fetch | git pull | git cloneПри , напечатанные значения:

// action => original_cmd who
git push => git-receive-pack 'BradeHyj/ToyProject.git' key-11
git fetch => git-upload-pack 'BradeHyj/ToyProject.git' key-11
git pull => git-upload-pack 'BradeHyj/ToyProject.git' key-11
git clone => git-upload-pack 'BradeHyj/ToyProject.git' key-11

git-receive-pack - Receive what is pushed into the repository

git-upload-pack - Send objects packed back to git-fetch-pack

На что указывает вышеизложенное?Когда мы выполняем операцию git push локально, она включает в себя операцию входа на сервер для выполнения команд (и за этой операцией входа следуют команды, распознаваемые gitlab-shell), напишите конкретную точку:

# git push
ssh user@host:port git-receive-pack 'BradeHyj/ToyProject.git'

Выше мы объяснили, как GitLab Shell получает клиентский ssh-запрос, и вернемся к переменнымwhoиoriginal_cmd:

  • who : параметры, передаваемые, когда sshd вызывает GitLab Shell.
  • original_cmd : упоминалось ранее$SSH_ORIGINAL_COMMANDпеременная, которая удаляется после выборки

Заинтересованные могут просверлить Pro Git 2 о SSH интеллектуальной передачи протокола, следующим образом:git-triplegate.com/book/this/v1/…

Все команды git, выполняемые gitlab-shell, будут проверять разрешения перед их фактическим выполнением, как показано в следующем коде.

# lib/gitlab-shell.rb
...
  def verify_access
    status = api.check_access(@git_access, nil, @repo_name, @who || @gl_id, '_any', GL_PROTOCOL)

    raise AccessDeniedError, status.message unless status.allowed?

    status
  end

Что такое Git-хуки

Логика обработки GitLab Shell основана на скрипте git hook.Все репозитории кода хранятся на стороне сервера GitLab.hooksПапки связаны с/home/git/gitlab-shell/hooksсередина, поэтому очень важно понимать логику выполнения скрипта хука gitlab-shell


Вот ссылка на введение Pro Git 2 в хуки на стороне сервера:git-triplegate.com/book/this/v2/…

Хуки хранятся в подкаталоге hooks каталога Git. То есть .git/hooks в большинстве проектов. Когда вы инициализируете новый репозиторий с помощью git init, Git по умолчанию помещает в этот каталог несколько примеров сценариев. Эти сценарии не только вызываются сами по себе, но и раскрывают переданные аргументы при их запуске. Все примеры представляют собой сценарии оболочки, некоторые из них смешаны с кодом Perl, но любой исполняемый сценарий с правильным именем будет работать нормально — вы можете написать их на Ruby, Python или на чем-то еще. Все имена примеров заканчиваются на .sample , если вы хотите включить их, вам нужно сначала удалить этот суффикс.

Сценарий ловушки активируется размещением исполняемого файла с правильным именем в подкаталоге hooks каталога Git. Таким образом, он может быть вызван Git

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

  • pre-receive: при обработке push-операции от клиента первым вызывается скрипт.pre-receive. Он получает серию отправленных ссылок из стандартного ввода. Если он выйдет с ненулевым значением, все нажатия не будут приняты. Вы можете использовать этот хук, чтобы предотвратить обновления ссылок без быстрой перемотки вперед или применить контроль доступа ко всем ссылкам и файлам, измененным в результате нажатия.
  • update : updateсценарий иpre-receiveСкрипт очень похож, за исключением того, что он работает один раз для каждой ветви, который готов к обновлению. Если толкатель толкает содержимое в несколько ветвей одновременно,pre-receiveЗапустить только один раз, тогда какupdateбудет запускаться один раз для каждой нажатой ветки. Вместо чтения со стандартного ввода он принимает три аргумента: имя ссылки (ветки), значение SHA-1 того, на что ссылка указывала перед отправкой, и значение SHA-1 того, что собирается сделать пользователь. толкать. еслиupdateЕсли скрипт завершится с ненулевым значением, будет отклонена только соответствующая ссылка, остальные все равно будут обновлены.
  • post-receive : post-receiveХуки запускаются после всего процесса и могут использоваться для обновления других системных служб или уведомления пользователей. он принимаетpre-receiveТе же стандартные входные данные. Его использование включает в себя отправку письма в список рассылки, уведомление сервера непрерывной интеграции или обновление системы отслеживания заявок — даже анализ сообщений фиксации, чтобы определить, является ли заявка проблемой. Следует включить, изменить или отключить. Сценарий не может остановить процесс отправки, но клиент будет оставаться подключенным до тех пор, пока не закончит свою работу, поэтому используйте его с осторожностью, если вы хотите сделать что-то еще, так как это займет у вас много времени.

Давайте сначала посмотрим на gitlab-shellpre-receiveЛогика (следующие примеры кодов находятся в$gitlab-shell/hooksпапка)


Видно, что перед отправкой (git-receive-pack) в репозиторий сервера необходимо выполнить такие приготовления, как авторизация пользователя и авторизация.


post-receiveТочно так же сpre-receiveРазница в основном в том, что логика выполнения отличается


После каких-либо команд GIT для операций репозитории на стороне серверов выполнены, рельсы GitLabpost_receiveИнтерфейс обрабатывает последующую логику


Введение в компоненты оболочки GitLab

Компонент оболочки GitLab обрабатывает все сеансы GitLab git SSH. Когда пользователь получает доступ к GitLab через SSH (например, git pull/push через ssh), компонент GitLab Shell делает следующее:

  1. Запретить пользователям использовать предопределенные команды git (git push, git pull и т. д.)
  2. Вызвать интерфейс API GitLab Rails, чтобы проверить, авторизован ли пользователь, и определить, к какому серверу Gitaly пользователь обращается к репозиторию кода (основная функция компонента Gitaly — выполнять операции, связанные с репозиторием кода)
  3. Копируйте данные туда и обратно между клиентом SSH и сервером Gitaly.

Когда мы выполняем git pull/push через ssh, происходит следующее:

  1. git pull over ssh -> gitlab-shell -> вызов API-интерфейса gitlab-rails для аутентификации информации о пользователе и авторизации -> успешная или неудачная авторизация -> установить сеанс Gitaly
  2. git push over ssh -> gitlab-shell (команда git сервера еще не была выполнена в это время) -> установить сеанс Gitaly -> выполнить сценарий предварительного приема gitlab-shell на сервере Gitaly -> вызов API-интерфейс gitlab-rails Для аутентификации информации о пользователе и авторизации -> успех или неудача авторизации

По историческим причинам компонент gitlab-shell также содержит скрипты ловушек, которые позволяют GitLab проверять команду пользователя git push (например, чтобы определить, есть ли у текущего пользователя разрешение на отправку изменений локального кода в защищенную ветку). также запускать события GitLab (например, когда пользователь успешно отправляет код для запуска конвейера CI и т. д.). В текущей архитектуре скрипт git hook gitlab-shell принадлежит компоненту Gitaly, и скрипт ловушки будет работать только на сервере Gitaly. Компонент gitlab-shell на сервер Gitaly устанавливать не обязательно, подробнее см.git lab.com/git lab-org/…

приложение

Ссылка на ссылку

официальный репозиторий gitlab-shell

Pro git 2

GitLab Series 1. Введение в базовые функции и архитектуру
GitLab Series 2 Рабочая лошадка GitLab
Единорог GitLab Series 3