Add initial documentation
This commit is contained in:
186
docs/17_SECURITY_HARDENING_GUIDE.md
Normal file
186
docs/17_SECURITY_HARDENING_GUIDE.md
Normal file
@ -0,0 +1,186 @@
|
||||
# 17 · Security Hardening Guide — **Stella Ops**
|
||||
*(v2.0 — 12 Jul 2025)*
|
||||
|
||||
> **Audience** — Site‑reliability and platform teams deploying **the open‑source Core** in production or restricted networks.
|
||||
---
|
||||
|
||||
## 0 Table of Contents
|
||||
|
||||
1. Threat model (summary)
|
||||
2. Host‑OS baseline
|
||||
3. Container & runtime hardening
|
||||
4. Network‑plane guidance
|
||||
5. Secrets & key management
|
||||
6. Image, SBOM & plug‑in supply‑chain controls
|
||||
7. Logging, monitoring & audit
|
||||
8. Update & patch strategy
|
||||
9. Incident‑response workflow
|
||||
10. Pen‑testing & continuous assurance
|
||||
11. Contacts & vulnerability disclosure
|
||||
12. Change log
|
||||
|
||||
---
|
||||
|
||||
## 1 Threat model (summary)
|
||||
|
||||
| Asset | Threats | Mitigations |
|
||||
| -------------------- | --------------------- | ---------------------------------------------------------------------- |
|
||||
| SBOMs & scan results | Disclosure, tamper | TLS‑in‑transit, read‑only Redis volume, RBAC, Cosign‑verified plug‑ins |
|
||||
| Backend container | RCE, code‑injection | Distroless image, non‑root UID, read‑only FS, seccomp + `CAP_DROP:ALL` |
|
||||
| Update artefacts | Supply‑chain attack | Cosign‑signed images & SBOMs, enforced by admission controller |
|
||||
| Admin credentials | Phishing, brute force | OAuth 2.0 with 12‑h token TTL, optional mTLS |
|
||||
|
||||
---
|
||||
|
||||
## 2 Host‑OS baseline checklist
|
||||
|
||||
| Item | Recommended setting |
|
||||
| ------------- | --------------------------------------------------------- |
|
||||
| OS | Ubuntu 22.04 LTS (kernel ≥ 5.15) or Alma 9 |
|
||||
| Patches | `unattended‑upgrades` or vendor‑equivalent enabled |
|
||||
| Filesystem | `noexec,nosuid` on `/tmp`, `/var/tmp` |
|
||||
| Docker Engine | v24.*, API socket root‑owned (`0660`) |
|
||||
| Auditd | Watch `/etc/docker`, `/usr/bin/docker*` and Compose files |
|
||||
| Time sync | `chrony` or `systemd‑timesyncd` |
|
||||
|
||||
---
|
||||
|
||||
## 3 Container & runtime hardening
|
||||
|
||||
### 3.1 Docker Compose reference (`compose-core.yml`)
|
||||
|
||||
```yaml
|
||||
services:
|
||||
backend:
|
||||
image: ghcr.io/stellaops/backend:1.5.0
|
||||
user: "101:101" # non‑root
|
||||
read_only: true
|
||||
security_opt:
|
||||
- "no-new-privileges:true"
|
||||
- "seccomp:./seccomp-backend.json"
|
||||
cap_drop: [ALL]
|
||||
tmpfs:
|
||||
- /tmp:size=64m,exec,nosymlink
|
||||
environment:
|
||||
- ASPNETCORE_URLS=https://+:8080
|
||||
- TLSPROVIDER=OpenSslGost
|
||||
depends_on: [redis]
|
||||
networks: [core-net]
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "https://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
command: ["redis-server", "--requirepass", "${REDIS_PASS}", "--rename-command", "FLUSHALL", ""]
|
||||
user: "redis"
|
||||
read_only: true
|
||||
cap_drop: [ALL]
|
||||
tmpfs:
|
||||
- /data
|
||||
networks: [core-net]
|
||||
|
||||
networks:
|
||||
core-net:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
No dedicated “Redis” or “Mongo” sub‑nets are declared; the single bridge network suffices for the default stack.
|
||||
|
||||
### 3.2 Kubernetes deployment highlights
|
||||
|
||||
Use a separate NetworkPolicy that only allows egress from backend to Redis :6379.
|
||||
securityContext: runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation: false, drop all capabilities.
|
||||
PodDisruptionBudget of minAvailable: 1.
|
||||
Optionally add CosignVerified=true label enforced by an admission controller (e.g. Kyverno or Connaisseur).
|
||||
|
||||
## 4 Network‑plane guidance
|
||||
|
||||
| Plane | Recommendation |
|
||||
| ------------------ | -------------------------------------------------------------------------- |
|
||||
| North‑south | Terminate TLS 1.2+ (OpenSSL‑GOST default). Use LetsEncrypt or internal CA. |
|
||||
| East‑west | Compose bridge or K8s ClusterIP only; no public Redis/Mongo ports. |
|
||||
| Ingress controller | Limit methods to GET, POST, PATCH (no TRACE). |
|
||||
| Rate‑limits | 40 rps default; tune ScannerPool.Workers and ingress limit‑req to match. |
|
||||
|
||||
## 5 Secrets & key management
|
||||
|
||||
| Secret | Storage | Rotation |
|
||||
| --------------------------------- | ---------------------------------- | ----------------------------- |
|
||||
| **Client‑JWT (offline)** | `/var/lib/stella/tokens/client.jwt` (root : 600) | **30 days** – provided by each OUK |
|
||||
| REDIS_PASS | Docker/K8s secret | 90 days |
|
||||
| OAuth signing key | /keys/jwt.pem (read‑only mount) | 180 days |
|
||||
| Cosign public key | /keys/cosign.pub baked into image; | change on every major release |
|
||||
| Trivy DB mirror token (if remote) | Secret + read‑only | 30 days |
|
||||
|
||||
Never bake secrets into images; always inject at runtime.
|
||||
|
||||
> **Operational tip:** schedule a cron reminding ops 5 days before
|
||||
> `client.jwt` expiry. The backend also emits a Prometheus metric
|
||||
> `stella_quota_token_days_remaining`.
|
||||
|
||||
## 6 Image, SBOM & plug‑in supply‑chain controls
|
||||
|
||||
* Images — Pull by digest not latest; verify:
|
||||
|
||||
```bash
|
||||
cosign verify ghcr.io/stellaops/backend@sha256:<DIGEST> \
|
||||
--key https://stella-ops.org/keys/cosign.pub
|
||||
```
|
||||
|
||||
* SBOM — Each release ships an SPDX file; store alongside images for audit.
|
||||
* Third‑party plug‑ins — Place in /plugins/; backend will:
|
||||
* Validate Cosign signature.
|
||||
* Check [StellaPluginVersion("major.minor")].
|
||||
* Refuse to start if Security.DisablePluginUnsigned=false (default).
|
||||
|
||||
## 7 Logging, monitoring & audit
|
||||
|
||||
| Control | Implementation |
|
||||
| ------------ | ----------------------------------------------------------------- |
|
||||
| Log format | Serilog JSON; ship via Fluent‑Bit to ELK or Loki |
|
||||
| Metrics | Prometheus /metrics endpoint; default Grafana dashboard in infra/ |
|
||||
| Audit events | Redis stream audit; export daily to SIEM |
|
||||
| Alert rules | Feed age ≥ 48 h, P95 wall‑time > 5 s, Redis used memory > 75 % |
|
||||
|
||||
## 8 Update & patch strategy
|
||||
|
||||
| Layer | Cadence | Method |
|
||||
| -------------------- | -------------------------------------------------------- | ------------------------------ |
|
||||
| Backend & CLI images | Monthly or CVE‑driven docker pull + docker compose up -d |
|
||||
| Trivy DB | 24 h cron via FeedMerger | configurable (FeedMerger.Cron) |
|
||||
| Docker Engine | vendor LTS | distro package manager |
|
||||
| Host OS | security repos enabled | unattended‑upgrades |
|
||||
|
||||
## 9 Incident‑response workflow
|
||||
|
||||
* Detect — PagerDuty alert from Prometheus or SIEM.
|
||||
* Contain — Stop affected Backend container; isolate Redis RDB snapshot.
|
||||
* Eradicate — Pull verified images, redeploy, rotate secrets.
|
||||
* Recover — Restore RDB, replay SBOMs if history lost.
|
||||
* Review — Post‑mortem within 72 h; create follow‑up issues.
|
||||
* Escalate P1 incidents to <security@stella‑ops.org> (24 × 7).
|
||||
|
||||
|
||||
## 10 Pen‑testing & continuous assurance
|
||||
|
||||
| Control | Frequency | Tool |
|
||||
|-------------------|-------------------|
|
||||
| OWASP | ZAP baseline | Each merge to main GitHub Action zap-baseline-scan |
|
||||
| Dependency scanning | Pull request | Trivy FS + GitHub Dependabot |
|
||||
| External red‑team | Annual or before GA | 3rd‑party CREST‑accredited vendor |
|
||||
|
||||
## 11 Vulnerability disclosure & contact
|
||||
|
||||
* Preferred channel: security@stella‑ops.org (GPG key on website).
|
||||
* Coordinated disclosure reward: public credit and swag (no monetary bounty at this time).
|
||||
|
||||
## 12 Change log
|
||||
|
||||
| Version | Date | Notes |
|
||||
| ------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| v2.0 | 2025‑07‑12 | Full overhaul: host‑OS baseline, supply‑chain signing, removal of unnecessary sub‑nets, role‑based contact e‑mail, K8s guidance. |
|
||||
| v1.1 | 2025‑07‑09 | Minor fence fixes. |
|
||||
| v1.0 | 2025‑07‑09 | Original draft. |
|
Reference in New Issue
Block a user