Когда Terraform просит логин у GitLab: разбираемся с токенами и сохранением доступа
Частый сценарий: инфраструктура описана в Terraform, а переиспользуемые модули лежат в приватном репозитории GitLab.
В конфигурации Terraform указываем HTTPS адрес репозитория:
module "infrastructure" {
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git?ref=master"
}
После этого запускаем:
terraform init
И вместо автоматического скачивания модуля получаем запрос:
Username for 'https://gitlab.example.com':
Password for 'https://gitlab.example.com':
Обычно это означает одно из следующего:
- старый токен GitLab истёк;
- токен был отозван;
- у токена недостаточно прав;
- Git продолжает использовать старый сохранённый токен;
- на машине вообще не настроено сохранение учётных данных.
Разберёмся, почему Terraform просит логин и пароль, как создать новый токен и как сделать так, чтобы доступ к GitLab работал стабильно.
Почему Terraform вообще спрашивает логин
Terraform не реализует отдельный механизм авторизации для GitLab.
Когда в source используется Git репозиторий:
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git?ref=master"
Terraform внутри вызывает обычный Git и загружает репозиторий примерно так же, как если бы мы выполнили:
git clone https://gitlab.example.com/admins/terraform/terraform-code.git
Поэтому всё, что связано с авторизацией, определяется настройками Git на текущей машине:
- сохранёнными логинами и токенами;
- настройками
credential.helper; - системным хранилищем паролей;
- SSH ключами;
- переменными окружения;
- конфигурацией пользователя, от которого запускается Terraform.
Если обычный git clone не может получить доступ к репозиторию, Terraform тоже не сможет скачать модуль.
Что такое Personal Access Token в GitLab
Для доступа к приватным репозиториям GitLab по HTTPS вместо пароля аккаунта используется Personal Access Token, сокращённо PAT.
Это длинная строка, которая:
- привязана к конкретному пользователю GitLab;
- имеет ограниченный набор прав;
- имеет срок действия;
- может быть отозвана без смены пароля пользователя.
Для чтения приватного репозитория Terraform обычно достаточно права:
read_repository
Такой токен позволяет выполнять операции чтения:
git clone
git fetch
git pull
git ls-remote
При этом токен не выдаёт пользователю доступ к новым проектам. Пользователь, которому принадлежит PAT, уже должен иметь право читать нужный репозиторий.
Как создать новый Personal Access Token:
Зайдите в веб интерфейс GitLab под своим аккаунтом.
Откройте раздел управления токенами. В зависимости от версии GitLab путь может называться немного по-разному:
Edit profile → Access → Personal access tokens
или:
Preferences → Access Tokens
или:
User Settings → Access Tokens
При создании токена укажите:
- Name - понятное имя, например
terraform-readonly; - Expiration date - дату окончания действия;
- Scopes - как минимум
read_repository.
После этого нажмите:
Create personal access token
GitLab покажет значение токена только один раз.
Сразу скопируйте его и сохраните в надёжное место. Позже посмотреть этот же токен повторно не получится - при потере придётся создавать новый.
Не выдавайте токену лишние права. Если Terraform должен только скачивать модули, ему не нужны:
api
write_repository
sudo
admin_mode
Чем меньше прав у токена, тем меньше последствий будет при его утечке.
Как проверить токен без Terraform
Перед повторным запуском Terraform лучше проверить доступ обычной командой Git.
Можно выполнить полное клонирование:
git clone https://gitlab.example.com/admins/terraform/terraform-code.git
Но для проверки авторизации достаточно более лёгкой команды:
git ls-remote https://gitlab.example.com/admins/terraform/terraform-code.git
Git запросит логин:
Username for 'https://gitlab.example.com':
Вводим свой логин GitLab.
Затем появится запрос:
Password for 'https://username@gitlab.example.com':
Сюда вставляем Personal Access Token, а не пароль от аккаунта.
Для Git токен выглядит как обычный пароль, но GitLab использует его как отдельный механизм авторизации.
Во время вставки токена терминал обычно ничего не показывает: ни символы, ни звёздочки. Это нормально. Просто вставляем токен и нажимаем Enter.
Если авторизация прошла успешно, команда вернёт список веток и тегов:
6d8f97d81c8e1c5e1b73e30c26083f1d8c84e7ef HEAD
6d8f97d81c8e1c5e1b73e30c26083f1d8c84e7ef refs/heads/master
7fc4baf8f7c86f6e390c8e46eb248abf4af5b806 refs/tags/v1.2.0
Это означает, что:
- адрес репозитория указан правильно;
- GitLab доступен по сети;
- токен работает;
- у пользователя есть доступ к проекту;
- scope
read_repositoryнастроен правильно.
После этого можно снова запускать:
terraform init
Сохранится ли токен автоматически
Токен сохранится только в том случае, если у Git настроен credential helper.
Credential helper - это механизм, через который Git получает и сохраняет логины и токены.
В зависимости от операционной системы credentials могут храниться:
- в macOS Keychain;
- в Windows Credential Manager;
- в Linux Secret Service или другом менеджере секретов;
- в оперативной памяти;
- в обычном текстовом файле.
Проверить текущую настройку можно командой:
git config --show-origin --get-all credential.helper
Например, результат может выглядеть так:
file:/home/user/.gitconfig store
или:
file:C:/Program Files/Git/etc/gitconfig manager
или:
file:/Users/user/.gitconfig osxkeychain
Если команда ничего не выводит, значит credential helper, скорее всего, не настроен.
Можно также выполнить более простую проверку:
git config --global credential.helper
Но эта команда показывает только глобальную пользовательскую настройку. Helper также может быть настроен на системном или локальном уровне, поэтому вариант с --show-origin --get-all информативнее.
Настройка credential helper на macOS
На macOS Git может хранить credentials в системном Keychain.
Для включения helper выполните:
git config --global credential.helper osxkeychain
После этого снова проверьте доступ:
git ls-remote https://gitlab.example.com/admins/terraform/terraform-code.git
Git один раз попросит логин и токен, после чего сохранит их в Keychain.
Следующие команды уже не должны запрашивать пароль:
git fetch
git pull
terraform init
Если osxkeychain уже настроен на системном уровне, повторно добавлять его в глобальную конфигурацию не обязательно.
Настройка credential helper на Linux
На Linux есть несколько вариантов.
Хранение в системном менеджере секретов:
Если установлен helper libsecret, можно использовать его:
git config --global credential.helper libsecret
В этом случае токен будет храниться через системный Secret Service, а не в обычном текстовом файле.
Доступность helper можно проверить командой:
git help -a | grep credential-
В зависимости от дистрибутива и способа установки Git имя доступной команды может отличаться.
Временное хранение в памяти:
Можно настроить временный кэш:
git config --global credential.helper 'cache --timeout=3600'
Здесь 3600 - время хранения credentials в секундах.
Git запомнит токен примерно на один час, после чего снова начнёт его запрашивать.
Такой вариант удобен, если не хочется сохранять токен на диск.
Хранение в обычном файле:
Самый простой вариант:
git config --global credential.helper store
После первого ввода логина и токена Git сохранит их, как правило, в файле:
~/.git-credentials
Содержимое может выглядеть примерно так:
https://username:token@gitlab.example.com
Важно понимать: токен хранится в незашифрованном виде.
Поэтому store подходит только для локальной машины, если вы понимаете связанные с этим риски.
Для общих серверов, production систем и CI/CD такой способ использовать не стоит.
Что делать, если Git продолжает использовать старый токен
Иногда новый PAT уже создан, но Git всё равно возвращает ошибку:
HTTP Basic: Access denied
Причина может быть в том, что credential helper продолжает подставлять старый сохранённый токен.
В этом случае старые credentials необходимо удалить.
Универсальный вариант:
printf 'protocol=https\nhost=gitlab.example.com\nusername=username\n\n' \
| git credential reject
Замените:
gitlab.example.com
на адрес своего GitLab, а:
username
на свой логин.
После этого снова выполните:
git ls-remote https://gitlab.example.com/admins/terraform/terraform-code.git
Git должен заново запросить логин и пароль. В поле пароля вставляем новый PAT.
Также credentials можно удалить вручную.
На macOS:
Keychain Access
На Windows:
Credential Manager
На Linux - через используемый системный keyring или менеджер секретов.
Если используется credential.helper store, откройте:
~/.git-credentials
и удалите строку со старым токеном.
Почему новый токен может не работать
Если новый токен создан, но GitLab всё равно отклоняет доступ, проверьте несколько вещей.
У токена отсутствует read_repository:
Для клонирования приватного репозитория должен быть включён scope:
read_repository
Без него токен может существовать, но не иметь права читать Git репозиторий.
Пользователь не имеет доступа к проекту:
PAT наследует права своего пользователя.
Если пользователя удалили из проекта или группы, токен не сможет читать репозиторий, даже если у него включён read_repository.
Токен истёк:
Проверьте дату окончания действия PAT в GitLab.
После истечения срока токен перестаёт работать, а сохранённая запись в credential helper автоматически не обновляется.
спользуется старый токен:
Git может брать старый PAT из:
- Keychain;
- Windows Credential Manager;
~/.git-credentials;- системного keyring;
- переменной окружения;
- скрипта;
- CI/CD variable.
Поэтому после ротации токена важно удалить или обновить старое значение во всех местах, где оно могло быть сохранено.
Указан неправильный адрес репозитория:
Скопируйте HTTPS URL непосредственно из GitLab:
Code → Clone with HTTPS
Проверьте:
- имя GitLab сервера;
- namespace;
- название проекта;
- наличие
.git; - регистр символов;
- доступ пользователя к проекту.
Возвращаемся к Terraform
После того как команда:
git ls-remote https://gitlab.example.com/admins/terraform/terraform-code.git
отрабатывает успешно, запускаем:
terraform init
Если модуль уже был загружен, но нужно проверить обновления, можно использовать:
terraform init -upgrade
Для простой замены токена удалять каталог .terraform обычно не требуется.
Terraform при следующем обращении к Git использует актуальные credentials из настроенного helper.
Лучше фиксировать версию модуля
В примере используется ветка:
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git?ref=master"
Такой вариант работает, но ветка master может измениться в любой момент.
В результате одна и та же конфигурация Terraform сегодня и через неделю может скачать разные версии модуля.
Для более предсказуемой работы лучше использовать тег:
module "infrastructure" {
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git?ref=v1.2.0"
}
Или конкретный commit SHA:
module "infrastructure" {
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git?ref=6d8f97d81c8e1c5e1b73e30c26083f1d8c84e7ef"
}
Тег удобнее для обычного версионирования, а commit SHA даёт максимально строгую фиксацию исходного кода.
Если модуль лежит в подкаталоге
Если Terraform-модуль находится не в корне Git-репозитория, а внутри каталога, путь указывается после двойного слеша:
module "network" {
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git//modules/network?ref=v1.2.0"
}
Здесь:
https://gitlab.example.com/admins/terraform/terraform-code.git
- адрес репозитория,
а:
//modules/network
- путь к модулю внутри репозитория.
Если модуль лежит в корне, двойной слеш добавлять не нужно:
module "infrastructure" {
source = "git::https://gitlab.example.com/admins/terraform/terraform-code.git?ref=v1.2.0"
}
Не вставляйте токен прямо в `source`
Технически можно записать токен непосредственно в HTTPS URL:
module "infrastructure" {
source = "git::https://username:token@gitlab.example.com/admins/terraform/terraform-code.git?ref=v1.2.0"
}
Но так делать не стоит.
Токен может попасть:
- в Git-репозиторий с Terraform-кодом;
- в историю коммитов;
- в логи Terraform;
- в логи CI/CD;
- в историю команд;
- в резервную копию проекта;
- в вывод диагностических инструментов.
Даже если позже удалить токен из файла, он может остаться в истории Git.
Для локальной работы используйте credential helper.
Для CI/CD используйте защищённые переменные, deploy token, project access token или другой подходящий механизм.
Альтернатива HTTPS - SSH-ключи
Можно полностью отказаться от HTTPS токенов и настроить доступ по SSH.
Для этого:
- Создаём SSH-ключ.
- Добавляем публичную часть ключа в GitLab.
- Проверяем подключение.
- Меняем адрес модуля в Terraform.
Создать ключ можно командой:
ssh-keygen -t ed25519 -C "terraform@gitlab"
Публичный ключ обычно находится здесь:
~/.ssh/id_ed25519.pub
Его содержимое нужно добавить в GitLab:
Edit profile → Access → SSH keys
Проверяем подключение:
ssh -T git@gitlab.example.com
Проверяем доступ к репозиторию:
git ls-remote git@gitlab.example.com:admins/terraform/terraform-code.git
После этого меняем source:
module "infrastructure" {
source = "git::ssh://git@gitlab.example.com/admins/terraform/terraform-code.git?ref=v1.2.0"
}
Если модуль лежит в подкаталоге:
module "network" {
source = "git::ssh://git@gitlab.example.com/admins/terraform/terraform-code.git//modules/network?ref=v1.2.0"
}
Теперь авторизация будет выполняться через SSH ключ, а Personal Access Token для загрузки модулей больше не понадобится.
При этом закрытый SSH ключ тоже является секретом. Его нужно защищать, не добавлять в репозиторий и по возможности использовать вместе с passphrase и ssh-agent.
Что использовать в CI/CD
Для локальной машины Personal Access Token подходит нормально.
Для CI/CD лучше не использовать личный PAT сотрудника, потому что такой токен зависит от его аккаунта:
- пользователь может уволиться;
- аккаунт могут заблокировать;
- пользователя могут удалить из группы;
- токен может истечь;
- права пользователя могут измениться.
В GitLab CI/CD лучше использовать один из специальных механизмов.
CI_JOB_TOKEN:
GitLab автоматически создаёт переменную:
CI_JOB_TOKEN
Токен существует только во время выполнения job.
Для доступа к репозиторию обычно используется username:
gitlab-ci-token
Пример настройки Git:
git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/".insteadOf "https://gitlab.example.com/"
После этого Terraform сможет загружать HTTPS модули с того же GitLab:
terraform init
При доступе к другому приватному проекту может потребоваться разрешить исходному проекту использование job token в настройках целевого проекта.
Deploy Token:
Deploy Token не привязан к личному аккаунту пользователя.
Для чтения репозитория ему достаточно scope:
read_repository
Такой вариант подходит для внешней автоматизации, серверов сборки и систем развёртывания.
Project Access Token:
Project Access Token создаётся на уровне конкретного проекта.
Он удобен, когда автоматизации нужен отдельный технический доступ, не связанный с аккаунтом сотрудника.
Для загрузки репозитория достаточно:
read_repository
Deploy Key:
Deploy Key позволяет предоставить серверу SSH-доступ к репозиторию.
Для Terraform-модулей обычно достаточно ключа только для чтения.
Это хороший вариант для CI runner или отдельного сервера автоматизации.
Типовые ошибки
HTTP Basic: Access denied:
Обычно означает одно из следующего:
- токен указан неправильно;
- токен истёк;
- токен отозван;
- отсутствует
read_repository; - пользователь потерял доступ к проекту;
- Git подставляет старый сохранённый токен.
Сначала удалите старые credentials, затем проверьте доступ через:
git ls-remote https://gitlab.example.com/admins/terraform/terraform-code.git
repository not found:
Возможные причины:
- неправильный URL;
- проект был переименован или перенесён;
- пользователь не имеет доступа;
- используется токен другого пользователя;
- репозиторий находится в другой группе.
Скопируйте HTTPS URL непосредственно из интерфейса GitLab.
could not resolve host:
Это уже не ошибка токена.
Проверьте:
- DNS;
- VPN;
- proxy;
- адрес GitLab;
- доступность сервера из текущей сети.
Ошибка TLS-сертификата:
Например:
SSL certificate problem: unable to get local issuer certificate
Обычно это означает, что на машине отсутствует доверенный корневой сертификат внутреннего GitLab.
Правильное решение - установить корпоративный CA сертификат в системное хранилище доверенных сертификатов.
Не стоит отключать проверку TLS командой:
git config --global http.sslVerify false
Такая настройка снижает безопасность всех HTTPS подключений Git.
Git работает вручную, а Terraform продолжает спрашивать пароль:
Проверьте, от какого пользователя запускается Terraform.
Например:
whoami
Также проверьте:
echo "$HOME"
which git
git config --show-origin --get-all credential.helper
Terraform может запускаться:
- через
sudo; - внутри контейнера;
- от другого системного пользователя;
- через IDE;
- через CI runner;
- с другим значением
HOME.
В этом случае он использует другую конфигурацию Git и не видит credentials вашего пользователя.
Что важно помнить
Terraform не хранит GitLab токены самостоятельно.
Он использует обычный Git и его настройки.
Если Terraform просит:
Username for 'https://gitlab.example.com':
это означает, что Git не смог автоматически получить подходящие credentials.
Чаще всего проблема решается так:
- Создаём новый Personal Access Token.
- Выдаём ему только
read_repository. - Удаляем старый токен из credential helper.
- Проверяем доступ через
git ls-remote. - Настраиваем безопасное хранение credentials.
- Повторно запускаем
terraform init.
Для macOS удобно использовать:
git config --global credential.helper osxkeychain
Для Windows:
git config --global credential.helper manager
Для Linux лучше использовать системное хранилище секретов или Git Credential Manager.
Вариант:
git config --global credential.helper store
работает, но хранит токен в незашифрованном виде.
Для серверов и CI/CD лучше использовать:
CI_JOB_TOKEN;- Deploy Token;
- Project Access Token;
- SSH Deploy Key.
Итог
Если при загрузке Terraform-модулей из приватного GitLab появился запрос логина и пароля, почти всегда проблема находится не в Terraform, а на уровне Git-аутентификации.
Возможные причины:
- истёк старый Personal Access Token;
- токен был отозван;
- токен не имеет
read_repository; - пользователь потерял доступ к проекту;
- Git продолжает использовать старые credentials;
- credential helper не настроен;
- Terraform запускается в другом окружении.
Для восстановления доступа нужно:
- Создать новый Personal Access Token с правом
read_repository. - Ввести логин GitLab в поле username.
- Вставить PAT вместо пароля.
- Проверить доступ командой
git ls-remote. - Настроить credential helper.
- Повторно выполнить
terraform init.
После этого Terraform сможет стабильно скачивать модули из приватного GitLab без постоянного запроса логина и пароля.
Комментарии