Перейти к основному содержимому

Конфигурация хостов

Зачем это нужно​

У репозитория ровно один ключ — тот, которым Semaphore его клонирует. Этого достаточно, пока всё, что нужно задаче, находится в этом репозитории. На практике задача обращается и к другим местам, и каждому из них могут требоваться свои учётные данные:

Пунктирные стрелки — это и есть пробел: ключ репозитория этим серверам не предъявляется, поэтому задача завершается с ошибкой Permission denied или Authentication failed, как только к ним обращается. До сих пор оставалось два обходных пути: дать одному ключу доступ везде или зашить учётные данные в файлы репозитория.

Host config («Конфигурация хостов») решает эту проблему, не затрагивая репозиторий. Вы говорите Semaphore: «всякий раз, когда проект подключается к этому хосту или этому URL, используй вот эти учётные данные из хранилища ключей». Сопоставление применяется к каждому Git- и SSH-соединению задачи, откуда бы оно ни было открыто.

У вас естьЧто в репозиторииБез сопоставленияС сопоставлением
Приватный подмодуль на другом Git-сервере.gitmodules, указывающий на [email protected]:infra/common.gitgit submodule update отклоняется: ключ развёртывания основного репозитория там неизвестенСопоставление типа Host для gitlab.example.com с ключом, разрешённым на этом сервере
Приватные роли или коллекции в Ansible requirements.ymlsrc: https://gitlab.example.com/ansible/role-nginx.gitansible-galaxy install запрашивает логин и завершается ошибкойСопоставление типа URL для https://gitlab.example.com/ansible/ с токеном доступа GitLab
Приватные модули Terraform / OpenTofu, получаемые из Gitsource = "git::https://github.com/acme/tf-modules.git"terraform init не может скачать модульСопоставление типа URL для https://github.com/acme/ с SSH-ключом или токеном
Инвентарь, хостам которого нужен другой SSH-ключ, чем репозиториюИнвентарь с db-01.internal, db-02.internalВ инвентаре можно указать только один ключ, и ключ репозитория для этих хостов не подходитСопоставление типа Host для каждого имени хоста или одно сопоставление с ключом инвентаря для общего для них хоста

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

Как это работает​

Сопоставление — это правило из трёх частей: что сопоставлять (имя хоста или префикс URL), какие учётные данные из хранилища ключей использовать — и ничего больше. Semaphore устанавливает сопоставления проекта перед первой Git-командой задачи и удаляет их по её завершении. Каждое соединение, которое открывает задача, — от её собственного клонирования до модуля git внутри плейбука — проходит через них.

Страница находится в меню проекта под пунктом Repositories. Для добавления, изменения и удаления сопоставлений требуется право управлять ресурсами проекта — то же, что нужно для хранилища ключей.

Страница конфигурации хостов проекта с тремя сопоставлениями

Типы сопоставлений​

Нажмите Add mapping («Добавить сопоставление») и выберите, чему должно соответствовать сопоставление.

Хост​

Сопоставление типа Host («Хост») соответствует имени SSH-хоста, например github.com или gitlab.example.com, и требует ключ типа SSH. Всякий раз, когда задача открывает SSH-соединение с этим хостом, она аутентифицируется сопоставленным ключом: репозиторий или подмодуль, клонируемый по SSH, URL вида git@host:group/repo.git в requirements.yml, а также хосты инвентаря Ansible с таким именем. Если у ключа задан логин, он используется как имя SSH-пользователя для этого хоста.

Диалог добавления сопоставления с выбранным типом Host

URL​

Сопоставление типа URL соответствует URL репозитория вида https:// или http://. Оно может указывать на один репозиторий, https://gitlab.example.com/infra/network.git, либо заканчиваться на /, чтобы охватить все репозитории группы, https://gitlab.example.com/ansible/. Если подходят несколько сопоставлений, побеждает наиболее конкретный URL, поэтому сопоставление одного репозитория переопределяет сопоставление группы, в которую он входит.

Учётные данные определяют, как выполняется обращение к URL:

Учётные данныеЧто происходит
Ключ SSHURL переписывается в SSH-форму, и соединение аутентифицируется ключом. Логин ключа используется как SSH-пользователь, git — если у ключа логина нет.
Login with password («Логин с паролем»)Логин и пароль добавляются в URL и передаются по HTTPS. Оставьте логин пустым, чтобы использовать персональный токен доступа. Эти учётные данные принимает только URL вида https://, поэтому секрет никогда не передаётся в открытом виде.

URL не должен содержать собственных учётных данных, пробелов, кавычек и символа =.

Диалог изменения сопоставления URL с использованием логина с паролем

Где действуют сопоставления​

Сопоставления проекта устанавливаются перед первой Git-командой задачи и остаются в силе до её завершения. Они распространяются на:

  • клонирование и обновление репозитория шаблона, включая его подмодули;
  • роли и коллекции, устанавливаемые из requirements.yml, см. Зависимости Galaxy;
  • модули, загружаемые командами terraform init или tofu init;
  • Git-команды, запускаемые самим плейбуком или скриптом, например модулем Ansible git;
  • репозиторий инвентаря, хранящегося в Git;
  • хосты инвентаря, если их имени соответствует сопоставление типа Host;
  • просмотр веток и плейбуков репозитория в форме шаблона, а также опрос расписаний, запускаемых при новом коммите.

Задачи, отправляемые на удалённый раннер, получают сопоставления вместе с задачей, поэтому там они ведут себя точно так же.

Сопоставление переопределяет запись для того же хоста в общесерверной конфигурации SSH (ssh.config_path в конфигурации); все остальные записи этого файла продолжают работать. Сопоставлениям нужен Git-клиент командной строки, который используется по умолчанию (git_client: cmd_git); со встроенным клиентом go_git задача проекта с сопоставлениями завершается с поясняющей ошибкой, вместо того чтобы использовать неверные учётные данные.

Учётные данные​

Приватные ключи никогда не попадают на диск: каждое SSH-сопоставление держит свой ключ в SSH-агенте, который живёт столько же, сколько задача, а сгенерированная конфигурация SSH ссылается только на агент. Логин с паролем передаётся Git через окружение его конфигурации, а не в командной строке, и Git выводит в лог задачи исходный URL, поэтому секрет не появляется ни там, ни там.

Ключ, на который ссылается сопоставление, удалить нельзя; диалог подтверждения перечисляет использующие его сопоставления. Изменение типа такого ключа на тот, который сопоставление использовать не может, например превращение SSH-ключа сопоставления типа Host в логин с паролем, также отклоняется.

Пример​

Плейбук размещён на GitHub, использует подмодуль из самостоятельно размещённого GitLab и устанавливает роль из второй группы GitLab через requirements.yml:

# requirements.yml
- src: https://gitlab.example.com/ansible/role-nginx.git
version: v2.1.0

Три сопоставления позволяют задаче выполниться без каких-либо изменений в репозитории:

ТипХост или URLУчётные данные
Hostgithub.comКлюч развёртывания репозитория GitHub
URLhttps://gitlab.example.com/ansible/Токен доступа GitLab в виде логина с паролем
URLhttps://gitlab.example.com/infra/network.gitSSH-ключ, разрешённый только для этого репозитория

Резервные копии​

Сопоставления входят в резервную копию проекта. Они ссылаются на свои учётные данные по имени, поэтому восстановленный проект сохраняет их привязку к восстановленным ключам. Как и для любого ключа, само значение секрета не экспортируется.