Короткий ответ
Обычная переменная в `.gitlab-ci.yml` или workflow-файле хранится в открытом виде в Git-истории и видна всем, у кого есть доступ к репозиторию; секреты нужно хранить в защищённом хранилище секретов CI-системы (CI/CD Variables, GitHub Actions Secrets) или во внешнем менеджере секретов (Vault, AWS Secrets Manager), откуда они подставляются в пайплайн во время выполнения, не попадая в код.
Как это работает подробнее
защищённые переменные CI-системы хранятся отдельно от репозитория, маскируются в логах и доступны только во время выполнения джобы через переменные окружения. Внешние менеджеры секретов дополнительно позволяют централизованно управлять доступом, ротацией и аудитом.
Пример кода
example.yaml
# Неправильно — секрет в коде:
# script: psql -h db.example.com -U admin -p SuperSecret123 mydb
# Правильно — секрет из защищённой CI-переменной:
deploy:
script: psql -h db.example.com -U admin -p "$DB_PASSWORD" mydb
variables:
DB_PASSWORD: $CI_DB_PASSWORD # задана в Settings -> CI/CD -> Variables как protected/maskedЧто использовать на практике
- На практике. даже защищённые CI-переменные не абсолютная гарантия — нужно ограничивать, какие ветки/окружения могут их использовать (protected variables/environments), и быть аккуратным с выводом переменных в лог (`echo $DB_PASSWORD` выведет секрет, даже если он хранится правильно).
- Пример. Ожидаемое поведение: в логе пайплайна значение `$DB_PASSWORD` отображается как `[MASKED]`, а сам пароль нигде не виден в коде репозитория.
Подводные камни
- Частые ошибки. коммитят пароль «временно для теста» и забывают удалить — он остаётся в истории Git навсегда, даже если потом удалить файл; выводят секреты в лог при отладке командой `env` или `set -x` в bash-скрипте, из-за чего секрет попадает в открытые логи пайплайна.