Как расшифровать Vault File в момент исполнения pipeline

«Как расшифровать Vault File в момент исполнения pipeline» — вопрос из категории Безопасность, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В 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