Secrets Management — Bezpečná správa tajomstiev
Prečo je secrets management dôležitý
Každá aplikácia potrebuje tajomstvá — API kľúče, databázové heslá, TLS certifikáty, tokeny tretích strán. Spôsob, akým s nimi nakladáme, priamo ovplyvňuje bezpečnosť celej infraštruktúry.
Typické problémy bez správneho secrets managementu:
- Heslá commitnuté v Git repozitári (aj po zmazaní zostávajú v histórii)
- Zdieľané
.envsúbory posielané cez Slack alebo email - Rovnaké heslo používané naprieč prostrediami (dev / staging / prod)
- Žiadna rotácia — rovnaké credentials mesiace alebo roky
- Žiadny audit trail — nevieme kto, kedy a čo čítal
Dôsledky úniku:
- Kompromitácia databáz a služieb
- Finančné straty (zneužitie cloud API kľúčov)
- Regulačné pokuty (GDPR, PCI-DSS)
- Strata dôvery zákazníkov
HashiCorp Vault
Vault je najrozšírenejší open-source nástroj na centralizovanú správu tajomstiev.
Architektúra
┌─────────────────────────────────────┐
│ Vault Server │
│ ┌───────────┐ ┌────────────────┐ │
│ │ Storage │ │ Secret Engines │ │
│ │ Backend │ │ (KV, PKI, │ │
│ │ (Consul, │ │ Database, │ │
│ │ Raft, │ │ Transit) │ │
│ │ S3...) │ └────────────────┘ │
│ └───────────┘ ┌────────────────┐ │
│ ┌───────────┐ │ Policies │ │
│ │ Auth │ │ (ACL, RBAC) │ │
│ │ Methods │ └────────────────┘ │
│ └───────────┘ │
└─────────────────────────────────────┘
▲ ▲
│ │
┌────┴───┐ ┌─────┴─────┐
│ CLI │ │ API/SDK │
└────────┘ └───────────┘
Seal / Unseal
Vault sa po štarte nachádza v sealed stave — dáta sú zašifrované a neprístupné. Na unseal je potrebných N z M kľúčov (Shamir's Secret Sharing):
# Inicializácia — vygeneruje unseal kľúče a root token
vault operator init -key-shares=5 -key-threshold=3
# Unseal — treba opakovať 3× s rôznymi kľúčmi
vault operator unseal <key-1>
vault operator unseal <key-2>
vault operator unseal <key-3>
# Auto-unseal cez cloud KMS (produkčné prostredie)
seal "awskms" {
region = "eu-central-1"
kms_key_id = "alias/vault-unseal"
}
Secret Engines
| Engine | Použitie |
|---|---|
| KV v2 | Key-value úložisko s verzovaním |
| Database | Dynamické credentials pre PostgreSQL, MySQL, MongoDB |
| PKI | Generovanie TLS certifikátov |
| Transit | Encryption as a Service (šifrovanie bez odhalenia kľúča) |
| AWS/Azure/GCP | Dynamické cloud credentials |
# KV secret engine
vault secrets enable -path=secret kv-v2
vault kv put secret/myapp db_password="S3cur3P@ss!"
vault kv get secret/myapp
# Dynamické DB credentials
vault secrets enable database
vault write database/config/mydb \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@db:5432/mydb" \
allowed_roles="readonly"
vault write database/roles/readonly \
db_name=mydb \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
# Aplikácia si vyžiada credentials
vault read database/creds/readonly
# → username: v-token-readonly-abc123
# → password: A1b2C3d4E5f6
# → TTL: 1h (automaticky expiruje)
Policies
# policy: app-readonly.hcl
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
path "database/creds/readonly" {
capabilities = ["read"]
}
# Deny explicitne
path "secret/data/admin/*" {
capabilities = ["deny"]
}
vault policy write app-readonly app-readonly.hcl
vault token create -policy="app-readonly"
SOPS (Mozilla) — Encrypted files in Git
SOPS (Secrets OPerationS) šifruje hodnoty v YAML/JSON/ENV súboroch, pričom kľúče zostávajú čitateľné. Ideálne pre GitOps workflow.
Ako to funguje
# Pred šifrovaním (secrets.yaml)
db:
password: SuperSecret123
host: db.example.com
# Po šifrovaní (secrets.enc.yaml)
db:
password: ENC[AES256_GCM,data:abc123...,iv:...,tag:...]
host: db.example.com # nešifrované — vidíme štruktúru
sops:
kms:
- arn: arn:aws:kms:eu-central-1:123456:key/abc-def
version: 3.7.3
Použitie
# Šifrovanie s AWS KMS
sops --encrypt --kms "arn:aws:kms:eu-central-1:123:key/abc" \
secrets.yaml > secrets.enc.yaml
# Šifrovanie s AGE (lokálne, bez cloudu)
age-keygen -o keys.txt
export SOPS_AGE_KEY_FILE=keys.txt
sops --encrypt --age "age1..." secrets.yaml > secrets.enc.yaml
# Dešifrovanie
sops --decrypt secrets.enc.yaml
# Editácia — otvorí dešifrovaný súbor v $EDITOR
sops secrets.enc.yaml
# Integrácia s Helm
helm secrets upgrade myapp ./chart -f secrets.enc.yaml
Výhody SOPS
- Šifrované súbory žijú priamo v Git repozitári
- Code review funguje — vidíme aké kľúče sa menili
- Podpora viacerých KMS providerov (AWS, GCP, Azure, AGE, PGP)
- Jednoduchá integrácia s CI/CD a Helm
Kubernetes Sealed Secrets
Sealed Secrets od Bitnami riešia problém ukladania Kubernetes Secrets do Gitu.
Princíp
┌──────────────┐ kubeseal ┌──────────────────┐
│ Secret │ ──────────────► │ SealedSecret │
│ (plaintext) │ (asymetrické │ (šifrované, │
│ │ šifrovanie) │ safe for Git) │
└──────────────┘ └──────────────────┘
│
git push
│
▼
┌──────────────────┐
│ Sealed Secrets │
│ Controller │
│ (v klastri) │
│ → dešifruje │
│ → vytvorí Secret│
└──────────────────┘
Použitie
# Inštalácia controllera
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system
# Vytvorenie SealedSecret
kubectl create secret generic myapp-secret \
--from-literal=password=S3cret! \
--dry-run=client -o yaml | \
kubeseal --format yaml > myapp-sealed-secret.yaml
# Aplikovanie — controller dešifruje a vytvorí Secret
kubectl apply -f myapp-sealed-secret.yaml
AWS Secrets Manager / Parameter Store
AWS ponúka dva natívne služby na správu tajomstiev.
Secrets Manager
Plnohodnotný secrets management s automatickou rotáciou:
# Vytvorenie secretu
aws secretsmanager create-secret \
--name "prod/myapp/db" \
--secret-string '{"username":"admin","password":"S3cur3!"}'
# Čítanie
aws secretsmanager get-secret-value --secret-id "prod/myapp/db"
# Automatická rotácia cez Lambda
aws secretsmanager rotate-secret \
--secret-id "prod/myapp/db" \
--rotation-lambda-arn arn:aws:lambda:...:function:rotate-db \
--rotation-rules '{"AutomaticallyAfterDays": 30}'
Parameter Store (SSM)
Jednoduchšie a lacnejšie riešenie pre konfiguráciu a secrets:
# SecureString — šifrované cez KMS
aws ssm put-parameter \
--name "/prod/myapp/db_password" \
--type SecureString \
--value "S3cur3P@ss!"
# Čítanie
aws ssm get-parameter \
--name "/prod/myapp/db_password" \
--with-decryption
# Hierarchické čítanie
aws ssm get-parameters-by-path \
--path "/prod/myapp/" \
--with-decryption
Porovnanie
| Vlastnosť | Secrets Manager | Parameter Store |
|---|---|---|
| Cena | ~$0.40/secret/mesiac | Free tier (Standard) |
| Rotácia | Natívna (Lambda) | Manuálna |
| Cross-account | Áno (resource policy) | Obmedzená |
| Verzovanie | Áno | Áno |
| Veľkosť | 64 KB | 8 KB (Standard) |
Environment variables vs Secrets managers
Environment variables — riziká
# Typický anti-pattern
export DB_PASSWORD="SuperSecret123"
docker run -e DB_PASSWORD=$DB_PASSWORD myapp
# Problémy:
# 1. Viditeľné cez /proc/<pid>/environ
# 2. Logované v shell history
# 3. Zdedené child procesmi
# 4. Viditeľné v docker inspect
Secrets manager prístup
# Python — čítanie z Vault za behu
import hvac
client = hvac.Client(url='https://vault.example.com')
client.auth.kubernetes.login(role='myapp', jwt=sa_token)
secret = client.secrets.kv.v2.read_secret_version(
path='myapp',
mount_point='secret'
)
db_password = secret['data']['data']['db_password']
# Kubernetes — Vault Agent Injector
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "myapp"
vault.hashicorp.com/agent-inject-secret-db: "secret/data/myapp"
spec:
containers:
- name: myapp
# Secret sa objaví ako súbor /vault/secrets/db
Kedy sú env vars akceptovateľné
- Lokálny vývoj (s
.envv.gitignore) - CI/CD pipeline premenné (GitHub Actions Secrets, GitLab CI Variables)
- Kombinácia: env var obsahuje cestu k secretu, nie secret samotný
Secret Rotation
Pravidelná rotácia minimalizuje dopad prípadného úniku.
Stratégie rotácie
1. Automatická rotácia (ideálne)
# AWS Secrets Manager — každých 30 dní
aws secretsmanager rotate-secret \
--secret-id "prod/db" \
--rotation-rules '{"AutomaticallyAfterDays": 30}'
# Vault — dynamické credentials s TTL
vault write database/roles/app \
default_ttl="1h" max_ttl="24h"
# Credentials automaticky expirujú, aplikácia si vyžiada nové
2. Dual-secret rotácia (zero-downtime)
Fáza 1: Vytvor nový secret (v2), starý (v1) stále funguje
Fáza 2: Aktualizuj aplikácie na v2
Fáza 3: Zruš platnosť v1
3. Rotačný checklist
- Databázové heslá — každých 30-90 dní
- API kľúče — každých 90 dní
- TLS certifikáty — pred expiráciou (cert-manager automatizuje)
- SSH kľúče — každých 6-12 mesiacov
- Service account tokeny — krátkodobé (1h), automaticky obnovované
Best Practices
1. Least Privilege
# Vault policy — len čo aplikácia naozaj potrebuje
path "secret/data/myapp/db" {
capabilities = ["read"]
}
# NIE: path "secret/*" { capabilities = ["read", "list", "create"] }
2. Audit logging
# Vault audit log
vault audit enable file file_path=/var/log/vault-audit.log
# Každý prístup je zaznamenaný:
# {
# "auth": {"token_type": "service", "policies": ["app-readonly"]},
# "request": {"path": "secret/data/myapp", "operation": "read"},
# "response": {"data": {"keys": ["password"]}}
# }
3. Encryption at rest & in transit
- Secrets vždy šifrované na disku (AES-256)
- Komunikácia cez TLS (mTLS pre service-to-service)
- Vault Transit engine na šifrovanie aplikačných dát
4. Žiadne secrets v kóde
# Pre-commit hook — detekcia secrets
pip install detect-secrets
detect-secrets scan --all-files --baseline .secrets.baseline
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
5. Disaster recovery
- Zálohovanie Vault dát a unseal kľúčov (offline, šifrované)
- Testovanie obnovy zo zálohy
- Dokumentovaný incident response plán pre únik secrets
Porovnávacia tabuľka nástrojov
| Nástroj | Typ | Rotácia | Git-friendly | Dynamické credentials | Cena |
|---|---|---|---|---|---|
| HashiCorp Vault | Centralizovaný server | ✅ Automatická | ❌ (agent/API) | ✅ (DB, Cloud, PKI) | Open-source / Enterprise |
| SOPS | Šifrované súbory | ❌ Manuálna | ✅ Natívne | ❌ | Free (OSS) |
| Sealed Secrets | K8s controller | ❌ Manuálna | ✅ (SealedSecret) | ❌ | Free (OSS) |
| AWS Secrets Manager | Managed služba | ✅ Lambda rotácia | ❌ | ❌ | ~$0.40/secret/mes |
| AWS Parameter Store | Managed služba | ❌ Manuálna | ❌ | ❌ | Free (Standard) |
| Azure Key Vault | Managed služba | ✅ | ❌ | ❌ | Pay-per-use |
| GCP Secret Manager | Managed služba | ✅ | ❌ | ❌ | ~$0.06/10k operácií |
| CyberArk Conjur | Enterprise server | ✅ | ❌ | ✅ | Enterprise licencia |
| Doppler | SaaS | ✅ | ❌ | ❌ | Free tier / Paid |
Kedy čo použiť
- Malý tím, GitOps → SOPS + AGE
- Kubernetes → Sealed Secrets + External Secrets Operator
- Enterprise / multi-cloud → HashiCorp Vault
- Čisto AWS → Secrets Manager + Parameter Store
- Rýchly štart → Doppler alebo cloud-natívne riešenie
Zhrnutie
Secrets management nie je luxus — je to základ bezpečnej infraštruktúry. Kľúčové princípy:
- Nikdy necommituj secrets do Gitu v plaintext forme
- Centralizuj správu secrets (Vault, cloud manager)
- Rotuj pravidelne a automaticky kde sa dá
- Audituj každý prístup k tajomstvám
- Least privilege — každý komponent dostane len to, čo potrebuje
- Šifruj at rest aj in transit
- Detekuj náhodné úniky (pre-commit hooks, secret scanning)