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)

AssetThreatsMitigations
SBOMs & scan resultsDisclosure, tamperTLS‑in‑transit, read‑only Redis volume, RBAC, Cosign‑verified plug‑ins
Backend containerRCE, code‑injectionDistroless image, non‑root UID, read‑only FS, seccomp + CAP_DROP:ALL
Update artefactsSupply‑chain attackCosign‑signed images & SBOMs, enforced by admission controller
Admin credentialsPhishing, brute forceOAuth 2.0 with 12‑h token TTL, optional mTLS

2 Host‑OS baseline checklist

ItemRecommended setting
OSUbuntu 22.04 LTS (kernel ≥ 5.15) or Alma 9
Patchesunattended‑upgrades or vendor‑equivalent enabled
Filesystemnoexec,nosuid on /tmp, /var/tmp
Docker Enginev24.*, API socket root‑owned (0660)
AuditdWatch /etc/docker, /usr/bin/docker* and Compose files
Time syncchrony or systemd‑timesyncd

3 Container & runtime hardening

3.1 Docker Compose reference (compose-core.yml)

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.

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

PlaneRecommendation
North‑southTerminate TLS 1.2+ (OpenSSL‑GOST default). Use LetsEncrypt or internal CA.
East‑westCompose bridge or K8s ClusterIP only; no public Redis/Mongo ports.
Ingress controllerLimit methods to GET, POST, PATCH (no TRACE).
Rate‑limits40 rps default; tune ScannerPool.Workers and ingress limit‑req to match.

5 Secrets & key management

SecretStorageRotation
Client‑JWT (offline)/var/lib/stella/tokens/client.jwt (root : 600)30 days – provided by each OUK
REDIS_PASSDocker/K8s secret90 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‑only30 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:
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

ControlImplementation
Log formatSerilog JSON; ship via Fluent‑Bit to ELK or Loki
MetricsPrometheus /metrics endpoint; default Grafana dashboard in infra/
Audit eventsRedis stream audit; export daily to SIEM
Alert rulesFeed age ≥ 48 h, P95 wall‑time > 5 s, Redis used memory > 75 %

8 Update & patch strategy

LayerCadenceMethod
Backend & CLI imagesMonthly or CVE‑driven docker pull + docker compose up -d
Trivy DB24 h cron via FeedMerge Serviceconfigurable (FeedMerge.Cron)
Docker Enginevendor LTSdistro package manager
Host OSsecurity repos enabledunattended‑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

ControlFrequencyTool/Runner
OWASP ZAP baselineEach merge to mainGitHub Action zap-baseline-scan
Dependency scanningPer pull requestTrivy FS + Dependabot
External red‑teamAnnual or pre‑GACREST‑accredited third‑party

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

VersionDateNotes
v2.02025‑07‑12Full overhaul: host‑OS baseline, supply‑chain signing, removal of unnecessary sub‑nets, role‑based contact e‑mail, K8s guidance.
v1.12025‑07‑09Minor fence fixes.
v1.02025‑07‑09Original draft.