Ответ
HashiCorp Vault — это центральный элемент в нашей системе управления секретами и доступом для инфраструктуры. Я использую его для безопасного хранения credentials, выдачи динамических секретов для БД и управления доступом к облачным ресурсам.
1. Аутентификация (Authentication): "Кто ты?"
Vault поддерживает множество методов аутентификации (auth methods). В продакшене мы чаще всего используем:
- JWT/OIDC для людей: Разработчики и инженеры аутентифицируются через корпоративный SSO (например, Okta). Vault проверяет JWT-токен, выданный провайдером.
- Kubernetes Service Account для подов: Это основной метод для рабочих нагрузок внутри кластера K8s. Поды аутентифицируются, используя свой JWT-токен и роль службы.
# Конфигурация метода аутентификации Kubernetes в Vault vault auth enable kubernetes vault write auth/kubernetes/config token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - AppRole для автоматизации (CI/CD, Terraform): Для не-human сущностей, которым нужен доступ к секретам. CI-сервер (например, Jenkins) использует свой
role_idиsecret_idдля логина.
2. Авторизация (Authorization): "Что тебе можно?" Права доступа определяются политиками (policies), написанными на HCL. Политика привязывается к методу аутентификации и роли.
-
Пример политики, разрешающей pod'у читать секреты для своей БД:
# policy.hcl path "database/creds/myapp-role" { capabilities = ["read"] } path "secret/data/myapp/*" { capabilities = ["read"] }Эта политика позволяет читать динамические credentials для БД и статические конфиги по определенному пути.
-
Создание роли Kubernetes, которая связывает SA в K8s с политикой в Vault:
vault write auth/kubernetes/role/myapp-role bound_service_account_names=myapp-sa bound_service_account_namespaces=production policies=myapp-policy ttl=1hТеперь любой под в неймспейсе
productionс ServiceAccountmyapp-saможет аутентифицироваться в Vault и получит токен с политикойmyapp-policyна 1 час.
3. Практический пример: Получение динамического секрета БД из пода: Приложение в своем манифесте указывает ServiceAccount и использует sidecar-контейнер или библиотеку для взаимодействия с Vault.
# Фрагмент Deployment в Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
serviceAccountName: myapp-sa # SA, привязанная к роли в Vault
containers:
- name: app
image: myapp:latest
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-creds # Секрет, который будет обновляться Vault Agent
---
# Конфигурация Vault Agent Injector (аннотации к поду)
apiVersion: v1
kind: Pod
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp-role"
vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/myapp-role"
vault.hashicorp.com/agent-inject-template-db-creds: |
{{- with secret "database/creds/myapp-role" -}}
{
"username": "{{ .Data.username }}",
"password": "{{ .Data.password }}"
}
{{- end }}
В этом сценарии Vault Agent автоматически инжектируется в под, аутентифицируется, получает короткоживущие логин/пароль от БД и записывает их в том db-creds, откуда основное приложение их считывает. Credentials автоматически ротируются по истечении TTL.