Как вы шифруете и маскируете ключи в инфраструктуре как код (IaC) и CI/CD?

Ответ

Шифрование и маскировка — ключевые этапы защиты данных в IaC и пайплайнах. Я разделяю эти процессы.

1. Шифрование для IaC (Terraform, Ansible): Использую инструменты, которые шифруют значения прямо в файлах конфигурации, позволяя безопасно хранить их в Git.

  • Mozilla SOPS (Secrets OPerationS): Мой основной инструмент. Он шифрует значения YAML/JSON/ENV файлов, используя бэкенды (KMS, PGP, Age). Ключ управления доступом хранится отдельно от данных.

    Пример .sops.yaml для AWS KMS:

    creation_rules:
      - path_regex: .enc.yaml$
        kms: 'arn:aws:kms:eu-west-1:123456789012:key/abcd1234-5678-90ab-cdef-1234567890ab'
        aws_profile: production

    Шифрование файла:

    sops --encrypt --in-place secrets.enc.yaml

    Использование в Terraform через sops_decrypt_file:

    data "external" "secrets" {
      program = ["sops", "--decrypt", "--output", "/dev/stdout", "${path.module}/secrets.enc.yaml"]
    }
    
    resource "aws_instance" "app" {
      ...
      user_data = base64encode(templatefile("user_data.sh", {
        db_password = data.external.secrets.result["database_password"]
      }))
    }
  • HashiCorp Vault + Terraform Provider: Более безопасная альтернатива. Секреты вообще не попадают в репозиторий. Terraform запрашивает их у Vault во время plan/apply.

    data "vault_generic_secret" "db" {
      path = "secret/data/production/database"
    }
    output "db_password" {
      value     = data.vault_generic_secret.db.data["password"]
      sensitive = true # Маскировка вывода в консоли Terraform
    }

2. Маскировка в CI/CD логах: Это предотвращает случайную утечку секретов, если они будут выведены командой echo или в сообщении об ошибке.

  • В GitLab CI: Достаточно объявить переменную с флагом masked. GitLab автоматически заменит её значение на [MASKED] в логах джобов.
  • В GitHub Actions: Аналогично, при создании секрета в настройках репозитория он автоматически маскируется в логах.
  • В Jenkins: Используются Credentials Binding Plugin, который маскирует значения.

Важное правило: Даже зашифрованные с помощью SOPS файлы не должны содержать мастер-ключи или root-пароли. Для таких супер-секретов используется только Vault или ручная инъекция через CI/CD переменные.

Ответ 18+ 🔞

А, ну это же про секреты в конфигах! Тема, блядь, архиважная, потому что если накосячить — будет вам хиросима и нигерсраки в одном флаконе. Слушай сюда, я тебе сейчас на пальцах разложу, как не просрать пароли от базы данных на всеобщее обозрение.

Вот смотри, есть два подхода, и их нельзя путать, а то получится пизда рулю.

1. Шифрование для всяких Terraform и Ansible (IaC): Тут задача — чтобы твои конфиги с паролями можно было спокойно пихать в Git, и чтобы любой, кто утащит репозиторий, увидел там только абракадабру. Для этого есть инструменты, которые шифруют значения прямо в файлах.

  • Mozilla SOPS (Secrets OPerationS): Это, ёпта, мой любимый инструмент, просто ебушки-воробушки. Он умеет шифровать значения внутри YAML, JSON или ENV файлов. Суть в чём: ты пишешь файл с секретами, а SOPS его проходится и заменяет все важные значения на зашифрованную хуйню. А ключ для расшифровки (от KMS, PGP или Age) ты хранишь отдельно, его в репу не заливаешь. Гениально и просто.

    Вот пример конфига .sops.yaml для AWS KMS:

    creation_rules:
      - path_regex: .enc.yaml$
        kms: 'arn:aws:kms:eu-west-1:123456789012:key/abcd1234-5678-90ab-cdef-1234567890ab'
        aws_profile: production

    Чтобы зашифровать файл, пишешь:

    sops --encrypt --in-place secrets.enc.yaml

    А в Terraform потом расшифровываешь на лету:

    data "external" "secrets" {
      program = ["sops", "--decrypt", "--output", "/dev/stdout", "${path.module}/secrets.enc.yaml"]
    }
    
    resource "aws_instance" "app" {
      ...
      user_data = base64encode(templatefile("user_data.sh", {
        db_password = data.external.secrets.result["database_password"]
      }))
    }
  • HashiCorp Vault + Terraform Provider: Это уже для параноиков, но по-хорошему. Здесь секреты вообще нихуя не попадают в репозиторий. Ты в коде просто пишешь: "эй, Vault, дай-ка мне пароль от базы", и Terraform во время выполнения лезет за ним в хранилище.

    data "vault_generic_secret" "db" {
      path = "secret/data/production/database"
    }
    output "db_password" {
      value     = data.vault_generic_secret.db.data["password"]
      sensitive = true # Это маскировка вывода в консоли, чтобы не светить пароль в логах
    }

2. Маскировка в логах CI/CD (пайплайны): А вот это, друг мой, защита от самого себя, от кривых рук. Представь: ты в скрипте пайплайна по ошибке сделал echo $SUPER_PASSWORD, и этот пароль навеки впечатался в логи джобы, доступные половине команды. Чистая катастрофа! Чтобы такого не было, системы CI/CD умеют маскировать значения переменных.

  • В GitLab CI: Создаёшь переменную в настройках проекта и ставишь галочку masked. Всё, теперь если она где-то всплывёт в логах, GitLab автоматом заменит её на [MASKED]. Спасение, блядь.
  • В GitHub Actions: Тот же принцип — добавляешь секрет в настройках репы, и он маскируется.
  • В Jenkins: Там свои плагины для этого, типа Credentials Binding.

И главное правило, которое я вынес, ебать, кровью: Даже если ты зашифровал файл через SOPS, не вздумай туда пихать мастер-ключи от всей инфраструктуры или root-пароли. Для такого уровня секретности годится только Vault или ручное подкладывание через переменные CI/CD. А иначе — доверия ебать ноль ко всей этой системе. Понял да?