ADG Оставить заявку
Блог Автоматизация 5 мин чтения

Mozilla SOPS vs Ansible Vault: шифрование отдельных полей YAML в GitOps-пайплайне

Протестировали SOPS от Mozilla как альтернативу ansible-vault: шифрование отдельных полей YAML, нормальный diff в git, интеграция с AWS KMS и HashiCorp Vault.

Контекст момента

Mozilla SOPS (Secrets OPerationS) - инструмент для шифрования отдельных значений в YAML/JSON/ENV с поддержкой AWS KMS, GCP KMS и PGP

С ansible-vault мы жили несколько лет и в целом понимали его ограничения. Шифрование целого файла - это грубо, но терпимо, пока файл маленький и один человек его меняет. Когда в проекте появляются три-четыре DevOps-а и конфиги начинают меняться часто, ansible-vault превращается в источник боли.

Конкретный триггер: третий merge conflict за неделю в зашифрованном group_vars/all/vault.yml. Файл бинарный - мерджить невозможно, git не видит что там внутри, надо перешифровывать вручную. Плюс git diff на зашифрованный файл показывает бессмысленный поток байт. Ревью pull request в таком случае - формальность, а не реальная проверка.

Стали смотреть что есть.

Что такое SOPS

Mozilla SOPS (Secrets OPerationS) работает по другой модели: шифруются не файлы целиком, а значения отдельных ключей. Структура YAML остаётся в открытом виде, зашифрованы только сами значения. Это меняет картину принципиально.

До SOPS:

# group_vars/all/vault.yml - содержимое файла бинарное после ansible-vault encrypt
$ANSIBLE_VAULT;1.1;AES256
30363239383430653936643339383566...
(и ещё 40 строк такого же)

После SOPS:

db_password: ENC[AES256_GCM,data:k3Gh...,iv:abc...,tag:xyz...,type:str]
api_key: ENC[AES256_GCM,data:p9Rq...,iv:def...,tag:uvw...,type:str]
db_host: postgres.internal  # не секрет - в открытом виде
db_port: 5432               # не секрет - в открытом виде

git diff теперь показывает что изменилось по имени ключа. Merge conflict если и возникает - то только если два человека меняли одно и то же значение, и git умеет его разрешить нормально. Ревью становится осмысленным.

Ключи: KMS и PGP

SOPS поддерживает несколько способов управления ключами. Попробовали два.

AWS KMS - для проектов где инфраструктура в AWS. SOPS использует data key, зашифрованный через KMS. Расшифровка происходит автоматически если у исполнителя есть нужные IAM-права. Для GitLab CI это instance profile EC2-машины с runner-ом - никаких ключей в переменных не нужно вообще. Ротация: меняешь data key в KMS, перешифровываешь файлы через sops -r. Доступ к секрету отзывается через IAM-политику.

PGP - для окружений вне AWS и для локальной разработки. Добавляешь fingerprint-ы всех кому нужен доступ в .sops.yaml, файл шифруется под все ключи одновременно. Каждый расшифровывает своим PGP-ключом. Новый человек в команде: добавил его fingerprint, перешифровал файлы - и всё.

Конфиг .sops.yaml в корне репозитория:

creation_rules:
  - path_regex: environments/prod/.*
    kms: arn:aws:kms:eu-west-1:123456789:key/aaaaa-bbbbb-ccccc
    pgp: >-
      FINGERPRINT1,
      FINGERPRINT2
  - path_regex: environments/staging/.*
    pgp: >-
      FINGERPRINT1,
      FINGERPRINT2,
      FINGERPRINT3

Прод - KMS плюс несколько PGP для аварийного доступа. Стейджинг - только PGP, у всей команды есть доступ.

Интеграция с GitLab CI

В пайплайне всё сводится к одному вызову перед ansible-playbook:

before_script:
  - curl -LO https://github.com/mozilla/sops/releases/download/0.0.9/sops_linux_amd64 && mv sops_linux_amd64 /usr/local/bin/sops && chmod +x /usr/local/bin/sops
  - sops --decrypt environments/prod/secrets.yml > /tmp/decrypted-secrets.yml

deploy:
  script:
    - ansible-playbook -e @/tmp/decrypted-secrets.yml site.yml

Runner крутится на EC2 с нужным instance profile - IAM-права на KMS есть автоматически. Никаких VAULT_SECRET_ID или ключей в CI Variables. Расшифровка происходит прямо в job-е, файл кладётся в /tmp и не покидает runner.

Можно и по-другому: расшифровать в переменную окружения и передать напрямую, не записывая на диск:

export DB_PASSWORD=$(sops -d --extract '["db_password"]' environments/prod/secrets.yml)
ansible-playbook site.yml

Второй способ аккуратнее: расшифрованные данные не пишутся на диск вообще, живут только в памяти процесса.

Связка с HashiCorp Vault

Для проектов где Vault уже есть, SOPS - не конкурент. Там секреты живут в Vault, и вопрос git-шифрования не стоит. Но есть класс файлов которые всё равно нужно хранить в git: Ansible-переменные с конфигурацией не-секретного типа вперемешку с секретами, Terraform-переменные, файлы с environment-специфичными параметрами. Туда HashiCorp Vault не тянешь - не тот уровень.

SOPS закрывает именно этот случай: «нам нужно хранить yaml в git, там есть пять секретных полей из двадцати, мы не хотим ради этого поднимать отдельный сервис».

Про сопровождение инфраструктуры с Vault мы писали недавно - там полноценный secret management для динамических credentials и PKI. SOPS это другой инструмент для другой задачи: статические конфиги в Git с минимальными операционными расходами.

Что не понравилось

Две вещи которые надо учитывать.

Нет ключа - нет файла. Если потерял PGP-ключ или IAM-права отозваны - файл нечем расшифровать. Ansible-vault в этом смысле не отличается, но с PGP ошибка выглядит менее очевидно: SOPS молча говорит «нет ни одного подходящего ключа» и уходит с ненулевым кодом. Нужно следить за backup-ами ключей.

Частичное шифрование приучает расслабляться. Когда часть файла в открытом виде, появляется соблазн «ой это не секрет» - и в открытой части оказываются данные которые лучше бы шифровать. Надо договариваться в команде что считать секретом явно.

Где сейчас

Перевели два проекта. На одном - AWS KMS для прода, PGP для стейджинга. На другом - только PGP, AWS там нет. Merge-конфликты в зашифрованных файлах с переездом на SOPS прекратились.

Ansible-vault остался на трёх старых проектах - переводить их не спешим, работает и ладно. Но на новых проектах где несколько человек работают с Ansible-переменными, будем начинать с SOPS.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.