← [Раздел](README.md) · [Главная](../README.md)

# HashiCorp Vault и управление секретами

## Цель

Понять, зачем нужен **централизованный vault** для секретов, как устроены пути (paths), политики, динамические credentials и интеграция с Kubernetes и CI без хранения паролей в Git.

## Предварительно

- Понимание разницы: переменная окружения vs файл vs API.
- Docker для локального dev-режима Vault.

## Время

~50 минут.

## Проблема «секреты везде»

| Антипаттерн | Риск |
|-------------|------|
| `.env` в Git | Утечка через clone/fork |
| Один пароль БД на все среды | Компрометация staging = prod |
| Секрет в Helm values в открытом виде | Попадает в Git и Argo CD UI |
| Ручная ротация раз в год | Долгоживущие ключи |

**Vault** хранит секреты зашифрованно, выдаёт доступ по **политикам** и **аудиту**, поддерживает **динамические** учётки (TTL минуты/часы).

## Основные понятия

| Термин | Значение |
|--------|----------|
| **Mount** | Тип хранилища: `kv`, `database`, `pki`, `aws` |
| **Path** | Логический путь: `secret/data/myapp/config` |
| **Policy** | HCL-правила: кто может read/write |
| **Token** | Краткоживущий ключ доступа |
| **Auth method** | Kubernetes, JWT/OIDC, AppRole |

## Dev-режим (только обучение!)

```bash
docker run --rm -p 8200:8200 \
  -e VAULT_DEV_ROOT_TOKEN_ID=dev-only-token \
  -e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 \
  hashicorp/vault:1.16 vault server -dev
```

В другом терминале:

```bash
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=dev-only-token

vault secrets enable -path=secret kv-v2
vault kv put secret/learn/app db_user=app db_password=CHANGEME-demo
vault kv get secret/learn/app
```

**Никогда** не используйте `-dev` и токен `dev-only-token` в production.

## Политика least privilege

`policy-learn.hcl`:

```hcl
path "secret/data/learn/app" {
  capabilities = ["read"]
}

path "secret/metadata/learn/*" {
  capabilities = ["list"]
}
```

```bash
vault policy write learn-read policy-learn.hcl
```

Роль CI получает только `read` на один path, не `sudo`.

## Динамические секреты БД (концепт)

1. Vault подключается к PostgreSQL как admin.
2. Приложение запрашивает credential: Vault создаёт пользователя `v-token-abc` на 1 час.
3. По истечении TTL — автоматическое удаление.

Меньше риска, чем статический `app:password123` в ConfigMap.

## Kubernetes: Vault Agent Injector

Pod аннотируется — sidecar монтирует файл `/vault/secrets/db`:

```yaml
metadata:
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "learn-app"
    vault.hashicorp.com/agent-inject-secret-db: "secret/data/learn/app"
```

Приложение читает файл при старте; секрет не в manifest.

## CI: short-lived token

GitLab/GitHub выдаёт OIDC JWT → Vault auth method `jwt` → token на 10 минут → deploy.

Преимущества:

- нет долгоживущего `VAULT_TOKEN` в Variables;
- привязка к `ref` и `environment`.

## Audit log

Включите audit device (файл или socket):

```bash
vault audit enable file file_path=/vault/logs/audit.log
```

Логируются **запросы** (path, policy), **не значения** секретов — годится для [audit-evidence](../09-compliance/audit-evidence.md).

## Ротация

Runbook (упрощённо):

1. Создать новую версию в KV v2 (`vault kv put` → version 2).
2. Rolling restart приложений.
3. Отозвать старую версию / инвалидировать dynamic lease.
4. Записать тикет `SEC-ROTATE-xxx`.

## Альтернативы

| Решение | Когда |
|---------|-------|
| AWS Secrets Manager / GCP Secret Manager | Облако-native |
| SOPS + age | GitOps с шифрованием в репо |
| Sealed Secrets | Только K8s, статические секреты |

Vault универсален для гибрида и dynamic secrets.

## Самопроверка

1. Почему `vault server -dev` нельзя в prod?
2. Чем KV v2 лучше v1 для ротации?
3. Как pod в K8s получает секрет без plain text в YAML?
4. Что пишется в audit log Vault?

## Дальше

[Falco и runtime в K8s](falco-k8s-runtime.md) — обнаружение атак уже после деплоя.
