diff --git a/SECURITY.md b/SECURITY.md index 650a646..e5c7191 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -38,18 +38,26 @@ is a very different thing from an overlooked one. Full detail in | What | Status | | --- | --- | -| SNMP community committed in plaintext, shared across firewall, switch, UPS and BMC | Removed from `HEAD` and replaced with four distinct per-device SOPS-encrypted values. Rotated and verified on the firewall, the UPS and the BMC: each answers to its own new community and refuses the old one. **Not rotated on the switch**, which is not answering SNMP — so whether it still accepts the old community is unknown, not proven clean. **Still present in git history.** Treat the old string as public. | +| SNMP community committed in plaintext, shared across firewall, switch, UPS and BMC | Removed from `HEAD` and replaced with four distinct per-device SOPS-encrypted values. Rotated on all four devices; each answers to its own new community. The firewall, the UPS and the BMC additionally refuse the old one. **The switch still accepts its previous community alongside the new one** — see below. **The original shared string is also still present in git history.** Treat both as public. | | Grafana `admin`/`admin` with anonymous Admin access enabled | Fixed — anonymous auth off, password from SOPS | | Passphrase-encrypted TLS private keys under `certificates/` | Removed from `HEAD`, still reachable in history. Purge tooling and a runbook are provided; not yet run. | -The switch is the honest gap. `10.7.7.2` has returned `up == 0` for every scrape -the monitoring stack has ever taken — all four SNMP series begin together when -the stack was rebuilt, so the failure predates the rotation and is not evidence -that the rotation broke anything. Nor is its silence evidence that the old -community was removed. It is reachable at layer 3 on ICMP and TCP/80; only -UDP/161 fails, which is the signature of a wedged SNMP agent rather than a dead -device. Tracked separately in -[#22](https://github.com/Gerrrt/HomeLab/issues/22). +The switch is the honest gap, and it is a deliberate one. `neo` (10.7.7.2) is +rotated and polling, but it also still accepts the community it held before the +rotation, verified after a reboot so the result reflects its saved +configuration rather than a stale agent. Its firmware does not persist a +deletion from the SNMP community table: the row can be removed, applied and +saved, and the entry is still there after a restart. Each attempt also drops +the SNMP agent until the switch is rebooted, and it is the switch the whole +network runs through. + +The residual risk is accepted rather than overlooked. The community is +read-only, and reaching UDP/161 on `10.7.7.2` requires both a foothold on the +management VLAN and the specific pfSense rule that permits `10.0.99.20` to +reach it — it is not exposed beyond the management segment. The way to close it +without fighting the firmware is to overwrite that row with a fresh value +rather than delete it, on some future pass when the switch is already being +taken down for something else. Remediation is tracked in [`docs/roadmap.md`](docs/roadmap.md), with procedures in [`docs/runbooks/rotate-snmp-community.md`](docs/runbooks/rotate-snmp-community.md) diff --git a/docs/roadmap.md b/docs/roadmap.md index c2e0935..deef58e 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -5,13 +5,13 @@ inventory. Ordered roughly by how much it matters. ## Security -- [ ] **Finish the SNMP rotation on the MokerLink switch (`neo`, 10.7.7.2).** - pfSense, the APC and iLO are done — each answers to its own new community - and refuses the old one. The switch is not, and cannot be verified, - because it is not answering SNMP: `up{job="snmp"}` for `10.7.7.2` has - been `0` for every scrape the current stack has taken, so the failure - predates the rotation rather than being caused by it. Blocked on - [#22](https://github.com/Gerrrt/HomeLab/issues/22). +- [ ] **Retire the MokerLink switch's previous SNMP community.** All four + devices are rotated, but `neo` still accepts its old community alongside + the new one: its firmware does not persist a deletion from the community + table, and each attempt drops the SNMP agent until the switch is + rebooted. Low priority and accepted for now — the community is read-only + and reachable only from the management VLAN. Overwrite the row with a + fresh value rather than deleting it, next time the switch is down anyway. → [runbook](runbooks/rotate-snmp-community.md) - [ ] **Purge `certificates/` and the old community string from git history**, then regenerate the CA and leaf certificates. diff --git a/docs/security.md b/docs/security.md index 7fea25d..dbcfff0 100644 --- a/docs/security.md +++ b/docs/security.md @@ -59,7 +59,7 @@ repository must be treated as compromised: | What | Where | Status | | --- | --- | --- | -| SNMP community shared across all four devices | `snmp.yaml`, from commit `ee3d443` | Replaced with four distinct per-device values, SOPS-encrypted. Rotated on `morpheus`, `mjolnir` and `shiva`, each verified answering its new community and refusing the old. **Not rotated on `neo`** — see [#22](https://github.com/Gerrrt/HomeLab/issues/22) and the [runbook](runbooks/rotate-snmp-community.md) | +| SNMP community shared across all four devices | `snmp.yaml`, from commit `ee3d443` | Replaced with four distinct per-device values, SOPS-encrypted. Rotated on all four. `morpheus`, `mjolnir` and `shiva` verified answering the new community and refusing the old; `neo` answers the new one but still accepts its previous community — accepted risk, see [`SECURITY.md`](../SECURITY.md) and the [runbook](runbooks/rotate-snmp-community.md) | | Grafana `admin` / `admin` with anonymous Admin access | compose file | Fixed: password from SOPS, anonymous auth disabled | | Passphrase-encrypted TLS private keys | `certificates/`, added in `efb2632`, deleted in `647d90a` but reachable at `647d90a~1` | Still in history. **Purge and regenerate** — see [runbook](runbooks/purge-git-history.md) | @@ -79,11 +79,10 @@ The devices are polled with SNMPv2c, which transmits the community string in cleartext. Anyone with a port on the management VLAN can read it off a single packet. Two mitigations are in place, one only partly, and one is not: -- **Done, with one exception:** each device has its own community, so one - captured packet no longer grants read access to the whole fleet. Three are - confirmed live on the hardware. The switch's exists only in SOPS — it has - never been proven on the device, because `10.7.7.2` is not currently answering - polls ([#22](https://github.com/Gerrrt/HomeLab/issues/22)). +- **Done:** each device has its own community, confirmed live on all four, so + one captured packet no longer grants read access to the whole fleet. The + switch does still accept its own previous community as well — an accepted + residual, recorded in [`SECURITY.md`](../SECURITY.md). - **Done:** SNMP is reachable only on the management VLAN and the switch-management LAN, neither of which anything but specific trusted hosts can enter.