187 lines
8.8 KiB
Markdown
187 lines
8.8 KiB
Markdown
# 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. |
|