Files
K3S/docs/security.md
Sergey Antropoff eccc1c2a01 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 уже существовали)
2026-04-26 00:22:06 +03:00

285 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Безопасность
Стек безопасности: 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]
```