Представляем glaball для управления множеством GitLab-инстансов

В наиболее популярном случае иметь множество инсталляций GitLab — это антипаттерн. Однако обстоятельства бывают разными: специализация нашего бизнеса привела к тому, что мы администрируем десятки self-hosted GitLab-инстансов обслуживаемых клиентов. Периодически у нас возникает потребность проделать какие-то действия на всех GitLab«ах сразу, чтобы не тратить время на многократное повторение рутинных операций. Все началось с необходимости мониторинга за критическими обновлениями для GitLab. Но аппетиты росли: со временем нам уже хотелось искать по содержимому файлов во всех инсталляциях или даже создавать пользователей.

Расскажем о том, как мы решили эти задачи в рамках внутренней разработки, которую теперь публикуем как Open Source-проект под названием glaball.

9f14c338ca985e853f9cc26ffda9afd1.png

Существующие решения

Для выполнения нужных нам операций уже существовали некоторые инструменты. Однако все они, к сожалению, ориентированы на работу в рамках одного инстанса GitLab и не позволяют делать bulk-запросы сразу ко всем.

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

  • Библиотека go-gitlab — клиент для GitLab API, в частности, используемый и утилитой glab.

Последнюю библиотеку мы и решили взять за основу, потому что Go нам ближе (и быстрее). 

Реализация

При создании инструмента мы сформулировали следующие общие требования:

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

  2. Высокая скорость группировки и сортировки вывода объектов (пользователей, проектов и т.п.). Объединение в группы и сортировка по нескольким полям.

  3. Минимальное количество кода. Использование готовых поддерживаемых (обновляемых) библиотек, принцип DRY.

Как уже упоминалось, в основу легла библиотека go-gitlab, которая активно развивается большим сообществом (почти 400 контрибьюторов на GitHub). К ней были добавлены обертки для функций/методов, выполняемых параллельно на всех инстансах.

Также для соответствия поставленным требованиям были задействованы:

  • peterbourgon/diskv — файловое хранилище, используется в качестве кэша;

  • gregjones/httpcache — как наиболее простой и легко интегрируемый в нашем случае способ кэширования HTTP-запросов к GitLab API;

  • ahmetb/go-linq — LINQ из .NET для группировки/сортировки объектов. Требовалось что-то наподобие SQL, но использовать SQLite с дополнительными зависимостями не хотелось, а в другой реализации получилось слишком много строк кода.

Так появилась консольная утилита glaball, которая через GitLab REST API выполняет нужные действия на всех инсталляциях GitLab«а.

Возможности

Изначально glaball была написана для мониторинга наличия критических обновлений. Утилита следила за актуальностью версий GitLab и отправляла нам алерты, если вдруг в используемой версии GitLab найдена CVE, из-за чего требуется срочное обновление инсталляции. Однако использование этого мониторинга «завязано» на наши внутренние системы (мы рассказывал о них в этом докладе), поэтому публикация данного кода утилиты не принесет большой пользы внешним пользователям.

Зато со временем glaball оброс рядом других функций, которые нам часто были нужны при работе с GitLab«ами, чтобы сократить время и повысить эффективность работы инженеров эксплуатации. Именно они и легли в основу публикуемых теперь исходников.

1. Поиск по содержимому файлов

Мы добавили функцию поиска определенного контента в файлах с помощью регулярных выражений. Эта штука сильно пригодилась нам, когда мы массово переходили с werf 1.1 на 1.2. Вот как это работает:

glaball projects files search --filepath=".gitlab-ci.yml" --pattern="1.1"

681c84c7525d797b04f437cdb6fe9434.png

Так мы получаем список всех проектов, в которых используется werf 1.1. На его основе легко сформировать задачи инженерам со списком проектов для перехода на 1.2. 

2. Управление пользователями

Когда в команду приходит новый инженер, для него может быть заведен пользователь в нужных инсталляциях GitLab«а. С glaball это делается очень просто:

glaball users create --email=test@test.com --username=test-glaball --name="test glaball" --password=qwerty

561b402bf8b036d601996bfc75b08524.png

Аналогично, можно использовать glaball и для блокировки (block), удаления (delete), модификации (modify), поиска (search) пользователей. Пример со сменой пароля пользователю:

glaball users modify --by=username test-glaball --password=newpassw0rd

46e9ebb6cbf61685d44ea407f6d0c2c7.png

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

3. Проверка администраторов

Ещё одна операция по пользователям — вывод их списка. Например, полезной будет проверка, нет ли у нас лишних администраторов в GitLab:

glaball users list --admins=true --group_by=username

c023bb89c734e5277ffcaaeeef936510.png

… или администраторов с выключенной двухфакторной авторизацией:

glaball users list --admins=true --two_factor=disabled

8ebaa2df03dc55a85fdb10d523704925.png

А в дальнейшем можно автоматизировать эти операции постоянным мониторингом с алертами при соответствии определенным критериям.

4. Очистка GitLab Registry и другие schedules 

Для регулярной очистки GitLab Registry мы настраиваем задания werf cleanup через scheduled pipelines в репозиториях. Но иногда кто-то может об этом забыть — тогда, чтобы проверить наличие задач по очистке, используется glaball:

glaball projects pipelines schedules --active=false

2ac5c4d15162268aa40cb9e440b9fe48.png

Такая команда позволяет следить за тем, чтобы Registry не занимал слишком много места. Конкретно она является одним претендентом на автоматизированный мониторинг — очистка во всех репозиториях, где используется werf.

Примечание. Кстати, а что делать в случае таких ошибок, как на скриншоте выше? Необходимо разобраться в причинах её возникновения, а после устранения — повторно запустить операцию, указав только конкретный инстанс через флаг -f. Если ошибка возникла из-за превышенного rate limit на запросы к GitLab API (по умолчанию он выключен), стоит обратить внимание на параметр rate_limiter.enabled в конфиге нужного инстанса.

А в целом поддержка pipeline schedules с возможностью фильтрации по состоянию активно/неактивно позволяет проверять и другие вещи в репозиториях, которым задано расписание. Например:

  • если используется деплой по расписанию;

  • различные тесты по расписанию;

  • выключение тестовых окружений для разработки в конце рабочего дня (для экономии ресурсов).

5. Прочие операции

Команда для вывода списка репозиториев позволяет сортировать, группировать и фильтровать. Например, список заархивированных проектов:

glaball projects list --archived=true

c8155e72b44e9ec38e62634564aa29b7.png

… или список публичных репозиториев:

glaball projects list --visibility=public

9049c550e218503635f334f0d42e3b82.png

А с помощью команды whoami можно вывести информацию о текущем пользователе API.

2a12c5a4ab14f0989350988ef8fd39a8.png

Примечание по безопасности 

Считаем важным предупредить о том, что все токены в конфигурационном файле glaball хранятся в открытом виде. Для нашего применения в настоящий момент это допустимый компромисс, но в вашем случае всё может быть иначе.

Вот несколько связанных с этим рекомендаций:

  1. Во избежание утечки токенов надо установить корректные права на файл конфигурации и хранить его в надежном месте (по умолчанию он находится в домашней директории пользователя $HOME/.config/glaball/config.yaml).

  2. По возможности используйте токены с read_api scope (только чтение) и избегайте использования токенов от административных учетных записей GitLab, либо храните их в надежном месте.

  3. Создавайте пользовательские токены с ограниченным сроком действия, чтобы забытые или утерянные токены не могли быть использованы злоумышленниками спустя неопределенное время. 

Заключение

Это был полезный опыт работы с параллелизмом в Golang, а также с GitLab и его API. Надеемся на дальнейшее развитие проекта.

Пожалуй, самый большой недостаток, который есть сейчас, — это отсутствие возможности добавления нового GitLab-инстанса в конфигурацию через командный интерфейс. (Кстати, это отлично реализовано в утилите glab.) Приходится добавлять хосты и исправлять их настройки в конфиге вручную. Также нам не хватает модульных тестов: на данный момент они не реализованы ни в каком виде.

Если у вас есть какие-то идеи или пожелания по добавлению новых фич, приносите их в issues (или даже pull requests) на GitHub. И, конечно, будем рады новым звездам для проекта!

P.S.

© Habrahabr.ru