docs: полная документация проекта — docs/ и README.md для каждого аддона

- README.md: перепиcан как компактный обзор (98 строк) с навигацией по docs/
- docs/: 13 файлов — getting-started, architecture, configuration, addons,
  storage, security, cicd, observability, networking, operations,
  make-reference, molecule-testing, troubleshooting
- addons/*/README.md: 31 новый файл — описание, параметры, примеры кода
  для каждого из 34 аддонов (vault и external-secrets уже существовали)
This commit is contained in:
Sergey Antropoff
2026-04-26 00:22:06 +03:00
parent 1080e6a792
commit eccc1c2a01
45 changed files with 5838 additions and 1670 deletions

284
docs/security.md Normal file
View File

@@ -0,0 +1,284 @@
# Безопасность
Стек безопасности: HashiCorp Vault, External Secrets Operator, CrowdSec, Vaultwarden.
## HashiCorp Vault
Централизованное управление секретами, PKI, динамические credentials. Подробный README: [addons/vault/README.md](../addons/vault/README.md).
### Быстрый старт
```yaml
# group_vars/all/addons.yml
addon_vault: true
vault_mode: "standalone" # standalone | ha
vault_auto_unseal_type: "none" # none | k8s | aws | gcp | azure | transit
vault_injector_enabled: true # Vault Agent Injector
vault_ingress_host: "vault-hc.example.com"
vault_ingress_tls: true
```
```bash
make addon-vault
```
### Режимы auto-unseal
| Тип | Описание | Где хранятся ключи |
|---|---|---|
| `none` | Ручной unseal при каждом рестарте | Нигде — только у оператора |
| `k8s` | Ключи в Kubernetes Secret + unsealer Pod | Secret `vault-unseal-keys` |
| `aws` | AWS KMS | AWS KMS ключ |
| `gcp` | Google Cloud KMS | GCP KMS ключ |
| `azure` | Azure Key Vault | Azure Key Vault |
| `transit` | Другой Vault (transit engine) | Другой Vault |
Для homelab рекомендуется `k8s`:
```yaml
vault_auto_unseal_type: "k8s"
vault_auto_unseal_k8s_shares: 5
vault_auto_unseal_k8s_threshold: 3
```
### HA режим (3 ноды, Raft)
```yaml
vault_mode: "ha"
vault_ha_replicas: 3
vault_auto_unseal_type: "k8s" # обязателен для HA
```
### Инициализация (первый запуск)
После установки Ansible автоматически:
1. Инициализирует Vault (`vault operator init`)
2. Сохраняет ключи unseal в Secret (при `vault_auto_unseal_type: k8s`)
3. Unseals Vault
4. Выводит root token
### Vault Agent Injector — инжекция секретов в поды
```yaml
# Аннотации на Pod/Deployment:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "my-app"
vault.hashicorp.com/agent-inject-secret-config.env: "secret/myapp/config"
vault.hashicorp.com/agent-inject-template-config.env: |
{{- with secret "secret/myapp/config" -}}
DB_PASSWORD={{ .Data.data.db_password }}
API_KEY={{ .Data.data.api_key }}
{{- end }}
```
Секрет будет доступен в поде как `/vault/secrets/config.env`.
### Kubernetes Auth Method
```bash
# Включить Kubernetes auth в 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
# Создать роль:
vault write auth/kubernetes/role/my-app \
bound_service_account_names=my-app \
bound_service_account_namespaces=my-app \
policies=my-app-policy \
ttl=24h
```
### Helm чарты с Vault секретами
```yaml
# Chart values через External Secrets (рекомендуется)
# или через Vault Agent annotations на Pod
# Прямой pull из Vault (в init container):
initContainers:
- name: vault-auth
image: vault:latest
command:
- sh
- -c
- |
vault login -method=kubernetes role=my-app
vault kv get -field=password secret/myapp/db > /vault/secrets/db-password
env:
- name: VAULT_ADDR
value: "http://vault.vault.svc.cluster.local:8200"
volumeMounts:
- name: vault-secrets
mountPath: /vault/secrets
```
---
## External Secrets Operator
Синхронизирует секреты из Vault в Kubernetes Secrets автоматически. Подробный README: [addons/external-secrets/README.md](../addons/external-secrets/README.md).
### Быстрый старт
```yaml
addon_external_secrets: true
addon_vault: true # рекомендуется — ESO настраивается на Vault автоматически
external_secrets_vault_url: "http://vault.vault.svc.cluster.local:8200"
external_secrets_vault_role_id: "xxx" # после создания AppRole в Vault
```
Секрет в `vault.yml`:
```yaml
vault_eso_approle_secret_id: "xxx"
```
### Создать AppRole в Vault
```bash
vault auth enable approle
vault policy write eso-policy - <<EOF
path "secret/data/*" {
capabilities = ["read"]
}
EOF
vault write auth/approle/role/eso-role \
token_policies="eso-policy" \
token_ttl=1h \
token_max_ttl=4h
vault read auth/approle/role/eso-role/role-id
vault write -f auth/approle/role/eso-role/secret-id
```
### ExternalSecret — синхронизировать секрет
```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-app-secrets
namespace: my-app
spec:
refreshInterval: 1m
secretStoreRef:
name: vault-backend # ClusterSecretStore
kind: ClusterSecretStore
target:
name: my-app-secret # имя Kubernetes Secret
creationPolicy: Owner
data:
- secretKey: db-password
remoteRef:
key: secret/myapp
property: db_password
- secretKey: api-key
remoteRef:
key: secret/myapp
property: api_key
```
Использование в Deployment:
```yaml
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-app-secret
key: db-password
```
---
## CrowdSec
IDS/IPS система обнаружения вторжений. Анализирует логи ingress-nginx. Подробнее: [addons/crowdsec/README.md](../addons/crowdsec/README.md).
```yaml
addon_crowdsec: true
crowdsec_nginx_bouncer_enabled: true # блокировать IP через nginx
```
---
## Vaultwarden
Self-hosted менеджер паролей (Bitwarden-совместимый). Подробнее: [addons/vaultwarden/README.md](../addons/vaultwarden/README.md).
```yaml
addon_vaultwarden: true
vaultwarden_domain: "https://vault.example.com"
vaultwarden_signups_allowed: false
```
---
## Общие рекомендации
### Network Policies (Calico/Cilium)
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: my-app
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-nginx
namespace: my-app
spec:
podSelector:
matchLabels:
app: my-app
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- port: 8080
```
### Pod Security Standards
```yaml
# Namespace с restricted policy:
apiVersion: v1
kind: Namespace
metadata:
name: secure-app
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
```
### Non-root контейнеры
```yaml
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
```