145 lines
7.0 KiB
Markdown
145 lines
7.0 KiB
Markdown
# Internet-Facing Stack Lifecycle & Vulnerability Management
|
||
|
||
_Last updated: 2026-04-07 (UTC)_
|
||
|
||
## 1) Internet-facing application inventory (app, version, image digest)
|
||
|
||
> Source of truth for internet-facing targets: `results/*` host folders and their WhatWeb outputs.
|
||
> Operational owner must replace all `TBD` digest values with runtime evidence from `docker image inspect`/`docker ps --no-trunc`.
|
||
|
||
| Host/FQDN | Product/App | Deployed version evidence | Container image (repo:tag) | Image digest (sha256) | Evidence source |
|
||
|---|---|---|---|---|---|
|
||
| auth.lan.ddnsgeek.com | Authelia (auth portal) | Version not fingerprinted from external scan | TBD | TBD | `results/auth.../tcp_443_https_whatweb.txt` |
|
||
| edge.lan.ddnsgeek.com | Edge reverse-proxy/app entrypoint | Version not fingerprinted from external scan | TBD | TBD | `results/edge.../tcp_443_https_whatweb.txt` |
|
||
| familytree.lan.ddnsgeek.com | FamilyTree app (gunicorn-backed) | gunicorn detected, app version not fingerprinted | TBD | TBD | `results/familytree.../tcp_443_https_whatweb.txt` |
|
||
| gitea.lan.ddnsgeek.com | Gitea | Gitea detected; exact version not fingerprinted | TBD | TBD | `results/gitea.../tcp_443_https_whatweb.txt` |
|
||
| gotify.lan.ddnsgeek.com | Gotify | Version not fingerprinted from external scan | TBD | TBD | `results/gotify.../tcp_443_https_whatweb.txt` |
|
||
| grafana.lan.ddnsgeek.com | Grafana | Grafana login redirect observed; exact version not fingerprinted | TBD | TBD | `results/grafana.../tcp_443_https_whatweb.txt` |
|
||
| influxdb.lan.ddnsgeek.com | InfluxDB (behind auth) | Version not fingerprinted from external scan | TBD | TBD | `results/influxdb.../tcp_443_https_whatweb.txt` |
|
||
| kuma.lan.ddnsgeek.com | Uptime Kuma | Dashboard redirect observed; exact version not fingerprinted | TBD | TBD | `results/kuma.../tcp_443_https_whatweb.txt` |
|
||
| monitor-kuma.lan.ddnsgeek.com | Uptime Kuma (monitoring endpoint) | Dashboard redirect observed; exact version not fingerprinted | TBD | TBD | `results/monitor-kuma.../tcp_443_https_whatweb.txt` |
|
||
| nextcloud.lan.ddnsgeek.com | Nextcloud (Apache/PHP stack) | Apache 2.4.66, PHP 8.3.30 | TBD | TBD | `results/nextcloud.../tcp_443_https_whatweb.txt` |
|
||
| node-red.lan.ddnsgeek.com | Node-RED (behind auth) | Version not fingerprinted from external scan | TBD | TBD | `results/node-red.../tcp_443_https_whatweb.txt` |
|
||
| passbolt.lan.ddnsgeek.com | Passbolt | NGINX detected; exact Passbolt version not fingerprinted | TBD | TBD | `results/passbolt.../tcp_443_https_whatweb.txt` |
|
||
| portainer.lan.ddnsgeek.com | Portainer | Portainer detected; exact version not fingerprinted | TBD | TBD | `results/portainer.../tcp_443_https_whatweb.txt` |
|
||
| prometheus.lan.ddnsgeek.com | Prometheus (behind auth) | Version not fingerprinted from external scan | TBD | TBD | `results/prometheus.../tcp_443_https_whatweb.txt` |
|
||
| searxng.lan.ddnsgeek.com | SearXNG | `searxng/2026.4.5+474b0a55b` detected | TBD | TBD | `results/searxng.../tcp_443_https_whatweb.txt` |
|
||
| shifts.lan.ddnsgeek.com | Shifts app (nginx front-end) | nginx 1.29.7 | TBD | TBD | `results/shifts.../tcp_443_https_whatweb.txt` |
|
||
| stockfill.lan.ddnsgeek.com | Stockfill app (nginx front-end) | nginx 1.27.5 | TBD | TBD | `results/stockfill.../tcp_443_https_whatweb.txt` |
|
||
| traefik.lan.ddnsgeek.com | Traefik (behind auth) | Version not fingerprinted from external scan | TBD | TBD | `results/traefik.../tcp_443_https_whatweb.txt` |
|
||
|
||
### Required evidence commands (run on Docker host)
|
||
|
||
```bash
|
||
# Capture deployed containers with immutable image digest references
|
||
sudo docker ps --format '{{.Names}}\t{{.Image}}' --no-trunc
|
||
|
||
# Resolve image digests for inventory table
|
||
sudo docker image inspect <image:tag> --format '{{index .RepoDigests 0}}'
|
||
|
||
# Optional: export inventory as CSV for compliance tracking
|
||
sudo docker ps --format '{{.Names}},{{.Image}}' --no-trunc > internet-facing-runtime-images.csv
|
||
```
|
||
|
||
---
|
||
|
||
## 2) Monthly update window definition
|
||
|
||
## Standard cadence
|
||
- **Window:** Second Tuesday of every month, **02:00–06:00 UTC**.
|
||
- **Fallback window:** Second Wednesday of every month, **02:00–06:00 UTC**.
|
||
- **Emergency patch window (critical CVE only):** within **48 hours** of advisory triage.
|
||
|
||
## Scope per window
|
||
1. **OS packages** (host + VM base images): apply security and bugfix updates.
|
||
2. **Container base images**: rebuild/pull fresh immutable digests.
|
||
3. **Application releases**: patch/minor upgrades for internet-facing apps.
|
||
|
||
## Freeze and exception policy
|
||
- No deferral beyond one cycle without documented risk acceptance.
|
||
- Critical internet-facing CVEs (remote exploitable) cannot wait for the next regular window.
|
||
|
||
---
|
||
|
||
## 3) Pre-production smoke checks for critical apps
|
||
|
||
All updates must be promoted through pre-prod first. Minimum smoke checks:
|
||
|
||
### Nextcloud
|
||
- Login page loads.
|
||
- Test user login succeeds.
|
||
- File upload + download round trip succeeds.
|
||
- Background jobs/cron status healthy.
|
||
|
||
### Passbolt
|
||
- Login page loads.
|
||
- Browser extension/API auth succeeds.
|
||
- Secret create/read/update works for test vault.
|
||
- Email/notification queue healthy.
|
||
|
||
### Gitea
|
||
- Login succeeds.
|
||
- Repository clone + push with test repo succeeds.
|
||
- Webhook test delivery succeeds.
|
||
- Actions/runner (if enabled) executes sample workflow.
|
||
|
||
### Grafana
|
||
- Login succeeds.
|
||
- Datasource health checks pass.
|
||
- Key dashboards render without panel errors.
|
||
- Alert rule evaluation pipeline healthy.
|
||
|
||
### Shared gate for all critical apps
|
||
- HTTPS endpoint returns expected status.
|
||
- No new high/critical findings in pre-prod vulnerability scan.
|
||
- Error budget/SLO smoke threshold respected for 30 minutes post-deploy.
|
||
|
||
---
|
||
|
||
## 4) CVE advisory tracking mapped to deployed versions
|
||
|
||
Create/maintain a single register (`cve-register.csv` or ticket board) with these required fields:
|
||
|
||
- Product
|
||
- Deployed version
|
||
- Deployed image digest
|
||
- CVE ID
|
||
- CVSS score/severity
|
||
- Advisory source URL
|
||
- Affected version range
|
||
- Exploit status (known exploited: yes/no)
|
||
- Mitigation owner
|
||
- Target fix version
|
||
- Due date
|
||
- Status (Open / In-progress / Pending validation / Resolved)
|
||
|
||
### Advisory sources (minimum)
|
||
- Vendor advisories/release notes for each product (Nextcloud, Passbolt, Gitea, Grafana, etc.)
|
||
- NVD
|
||
- CISA KEV catalog (for known exploited CVEs)
|
||
|
||
### Mapping rule
|
||
A CVE can only be marked “Not Affected” when the deployed version + digest is proven outside vulnerable ranges with evidence attached.
|
||
|
||
---
|
||
|
||
## 5) Closure evidence requirement (hard gate)
|
||
|
||
A vulnerability ticket is only closed when **both** conditions are met:
|
||
|
||
1. **Version or digest changed in production**
|
||
- Before/after evidence attached (`docker image inspect`, deployment manifest diff, or SBOM diff).
|
||
2. **Post-update scan is clean for that CVE**
|
||
- Re-scan target service and attach artifact proving CVE no longer detected.
|
||
|
||
### Mandatory closure artifacts
|
||
- Screenshot/export of runtime version and image digest after deployment.
|
||
- Linked change request/deployment ID.
|
||
- Post-update vulnerability scan report.
|
||
- Smoke-test checklist execution evidence.
|
||
|
||
### Status workflow
|
||
`Open -> Planned -> In Progress -> Pending Validation -> Resolved`
|
||
|
||
`Resolved` is prohibited unless both hard-gate conditions above are satisfied.
|