- 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 уже существовали)
285 lines
7.1 KiB
Markdown
285 lines
7.1 KiB
Markdown
# Безопасность
|
||
|
||
Стек безопасности: 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]
|
||
```
|