Ответ
В CI/CD пайплайнах я использую несколько подходов для безопасной работы с секретами, в зависимости от используемого инструментария:
1. Ansible Vault (для конфигураций как код):
В Jenkins/GitLab CI настраиваю переменную окружения ANSIBLE_VAULT_PASSWORD или использую файл:
# .gitlab-ci.yml этап
decrypt_secrets:
stage: setup
script:
- echo "$ANSIBLE_VAULT_PASSWORD" > .vault_pass
- ansible-vault decrypt --vault-password-file .vault_pass secrets/production.yml
# Или для временного использования без сохранения файла:
- ansible-vault view --vault-password-file .vault_pass secrets/production.yml > decrypted_temp.yml
artifacts:
paths:
- secrets/production.yml
expire_in: 1 hour # Автоматическое удаление
2. HashiCorp Vault (интеграция через CLI или API):
# Пример для GitLab CI с JWT аутентификацией
variables:
VAULT_ADDR: "https://vault.example.com"
get_secrets:
script:
# Аутентификация через JWT (GitLab 14.1+)
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=gitlab-ci jwt=$CI_JOB_JWT)"
# Чтение секрета
- vault kv get -field=database_password secret/myapp/production > db_password.txt
# Или получение всего секрета как JSON
- vault kv get -format=json secret/myapp/production | jq -r '.data.data' > config.json
3. Cloud Native подход (Kubernetes Secrets + External Secrets Operator):
# Использую External Secrets для автоматической синхронизации
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: app-secrets
data:
- secretKey: DATABASE_PASSWORD
remoteRef:
key: myapp/production
property: database_password
4. Практические меры безопасности, которые я реализую:
- Никогда не коммичу пароли или токены в репозиторий
- Использую временные токены с минимальными правами и TTL
- Настраиваю IP whitelist для доступа к Vault из CI
- Логирую все операции с секретами для аудита
- Регулярно ротирую секреты и токены
- Для production использую отдельные Vault инстансы с усиленной изоляцией
Пример полного пайплайна с обработкой ошибок:
stages:
- setup
- deploy
setup_secrets:
stage: setup
script:
- |
if [ -z "$VAULT_TOKEN" ]; then
echo "ERROR: VAULT_TOKEN not set"
exit 1
fi
# Безопасное получение секрета с обработкой ошибок
if ! vault kv get -field=api_key secret/myapp/$CI_ENVIRONMENT_NAME > api.key; then
echo "ERROR: Failed to retrieve secret"
exit 1
fi
# Устанавливаю минимальные права
chmod 600 api.key
artifacts:
paths:
- api.key
expire_in: 30 minutes
cleanup:
stage: deploy
script:
- rm -f api.key # Принудительная очистка
when: always