(v2.0 — 12 Jul 2025)
Audience — Site‑reliability and platform teams deploying the open‑source Core in production or restricted networks.
- Threat model (summary)
- Host‑OS baseline
- Container & runtime hardening
- Network‑plane guidance
- Secrets & key management
- Image, SBOM & plug‑in supply‑chain controls
- Logging, monitoring & audit
- Update & patch strategy
- Incident‑response workflow
- Pen‑testing & continuous assurance
- Contacts & vulnerability disclosure
- Change log
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 |
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 |
services:
backend:
image: registry.stella-ops.org/stella-ops/stella-ops:<PINNED_TAG_OR_DIGEST>
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.
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).
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. |
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
.
- Images — Pull by digest not latest; verify:
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).
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 % |
Layer | Cadence | Method |
---|
Backend & CLI images | Monthly or CVE‑driven docker pull + docker compose up -d | |
Trivy DB | 24 h cron via FeedMerge Service | configurable (FeedMerge.Cron) |
Docker Engine | vendor LTS | distro package manager |
Host OS | security repos enabled | unattended‑upgrades |
- 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).
Control | Frequency | Tool/Runner |
---|
OWASP ZAP baseline | Each merge to main | GitHub Action zap-baseline-scan |
Dependency scanning | Per pull request | Trivy FS + Dependabot |
External red‑team | Annual or pre‑GA | CREST‑accredited third‑party |
- Preferred channel: security@stella‑ops.org (GPG key on website).
- Coordinated disclosure reward: public credit and swag (no monetary bounty at this time).
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. |