From 6248875e13b90b84e1750f632fe5667f91ddd19c Mon Sep 17 00:00:00 2001 From: Backtalk6858 Date: Thu, 9 Jul 2026 21:27:21 -0500 Subject: [PATCH] docs: add P1-HARDENING prompt (DNS bake, firewall persist+RFC1918 DROP, provisioning fix) Co-Authored-By: Claude Opus 4.8 --- agent-builder/agent_prompts.md | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/agent-builder/agent_prompts.md b/agent-builder/agent_prompts.md index 9936f24..a5ae5cd 100644 --- a/agent-builder/agent_prompts.md +++ b/agent-builder/agent_prompts.md @@ -1016,6 +1016,51 @@ Prefer `incus` over legacy lxc. Gather inventories with read-only commands (dpkg --- +## P1-HARDENING — finish + secure the sandbox substrate (2026-07-09) +> **Why this exists:** the P0+GROUNDWORK agent built the P1 base (Incus 6.0.4, btrfs loop pool, `incusbr0` NAT, both mirrors launched + isolated) but left three gaps discovered during a live networking-fix detour (see memory `incus-on-docker-host-networking`): (a) the sandbox internet fixes were applied **live only, not baked into `build-sandbox.sh`** — so the next rebuild wipes them; (b) the host iptables fix that lets the incus bridge forward is **not reboot-persistent AND too broad** (allows sandbox→LAN egress, undercutting isolation); (c) in-container provisioning was **truncated by the sudo-bridge 60s exec cap** and has a **useradd/usermod ordering bug** (adds `administrator` to groups before creating the user). This agent closes all three so P2 can start on a trustworthy, self-rebuilding sandbox. **This is P1 hardening ONLY — do not touch P2/P3/P4/P5.** + +**Blast radius: server-01 sandbox-side + server-01 host iptables/boot config** (no production containers, no primary, no live data). `--max-turns 30`. + +``` +You are an infrastructure-hardening agent finishing the Agent-Sudo sandbox substrate on server-01 (192.168.1.90). The base P1 build is already done; you are closing three known gaps and proving isolation. DO NOT redesign anything and DO NOT begin P2 (service). Design is LOCKED in agent_sudo_design_decisions.md (D1, D7). + +## READ FIRST (do not re-derive — these are the exact, already-diagnosed fixes) +Read the memory file `/home/administrator/.claude/projects/-home-administrator-Desktop-claude/memory/reference_incus_on_docker_host_networking.md` — it contains BOTH networking fixes verbatim (Docker FORWARD DROP → DOCKER-USER accept; broken systemd-resolved → mask + static resolv.conf) and the incus-admin access note. Use those exact commands; do not rediscover them. + +## Use the shared block (verified facts, sudo-bridge-server01 path, tier-2-broken guard, wrap-up, loop guard). + +## EXECUTION PATH — two lanes, pick the cheaper one per command +- **Direct SSH as `administrator@192.168.1.90` (BatchMode, key-based):** `administrator` is now in the **`incus-admin`** group, so ALL `incus ...` commands and running `build-sandbox.sh` run over plain SSH with **NO 60s cap** (the cap is a sudo-bridge limitation — this is how you avoid the truncation that broke the groundwork run). Use this lane for every incus/container/provisioning/verification step. +- **sudo-bridge-server01 (`http://192.168.1.90:8082`, tier-1 only, per shared block):** use ONLY for root-owned writes `administrator` can't do — editing `build-sandbox.sh` (root:root) and host-level iptables/systemd. Obey the no-shell / single-argv / base64-write rules. If a host iptables/systemd step is NOT tier-1-eligible, DO NOT block on tier-2 (broken) — write the artifact and DEFER the privileged enable to the MANUAL-AUTH BATCH. + +## Contract — what must be true when you finish (or be cleanly deferred with a manual-auth list) +1. **DNS fix baked into `build-sandbox.sh`.** Right AFTER the `waiting for network` loop, the script must, for the launched container: `systemctl mask systemd-resolved`, stop it, and write a static `/etc/resolv.conf` (`nameserver 1.1.1.1` + the incusbr0 gateway resolver — confirm the gateway via `incus network get incusbr0 ipv4.address`). Idempotent (safe on rebuild). Verify: after a rebuild, `incus exec -- getent hosts deb.debian.org` returns IPs, exit 0 — WITHOUT any manual post-fix. +2. **Provisioning bug fixed + provisioning completes.** In `build-sandbox.sh`, reorder so every user is **created before** any `usermod -aG`/group-membership step (the current script adds `administrator` to groups before `useradd`). Make the whole provisioning block idempotent (`getent passwd X || useradd ...`, `getent group Y || groupadd ...`). Because you run via direct SSH (no 60s cap), provisioning must now run to completion. Verify: after rebuild, the mirrored users/groups/path-skeleton from the inventory JSON are all present in the container with NO ordering error in the run output. +3. **Host iptables made persistent AND tightened (close the LAN-egress hole).** The live `iptables -I DOCKER-USER -i/-o incusbr0 -j ACCEPT` rules are (a) wiped by reboot / `systemctl restart docker`, and (b) too broad — they let a sandbox reach 192.168.1.x / other RFC1918. Produce a **single boot-persistent mechanism** (a small systemd unit, e.g. `incus-sandbox-firewall.service`, `After=docker.service`, that reapplies the rules — because Docker rebuilds its chains on restart) that installs, in DOCKER-USER, this ORDER: + - ACCEPT established/related for incusbr0, + - from incusbr0 **DROP** to `192.168.0.0/16`, `10.0.0.0/8`, `172.16.0.0/12` **EXCEPT** the incusbr0 subnet itself (get it from `incus network get incusbr0 ipv4.address`) and the incusbr0 gateway (so container→gateway DNS still works), + - ACCEPT incusbr0 in/out otherwise (internet egress). + Net effect: sandbox reaches the internet (apt/DNS) but CANNOT reach the LAN. If installing/enabling the systemd unit is not tier-1-eligible via sudo-bridge, WRITE the unit file + a `restore-rules.sh` to `/opt/appdata/docker/agent-sudo/firewall/` and DEFER `systemctl enable --now incus-sandbox-firewall.service` to the MANUAL-AUTH BATCH. +4. **Both mirrors rebuilt clean from the hardened script and RE-PROVEN isolated.** Run `build-sandbox.sh server-01` then `build-sandbox.sh primary` over direct SSH. For BOTH containers confirm: RUNNING on incusbr0 with NO forwarded LAN port; `getent hosts deb.debian.org` exit 0 (internet OK); and — once the firewall rules are active — a LAN reach test FAILS (e.g. `incus exec -- ping -c1 -W2 192.168.1.88` times out / is dropped). If the firewall unit was deferred to manual-auth, run the DROP rules live to prove the isolation test, note they still need the persistent enable, and record it. + +## Pre-flight (idempotent) +- `ssh -o BatchMode=yes administrator@192.168.1.90 'incus list; incus network get incusbr0 ipv4.address'` — confirm both containers + the bridge subnet/gateway. +- Check whether the DOCKER-USER incusbr0 rules are currently present (`iptables -S DOCKER-USER` via sudo-bridge) — a docker restart since 2026-07-09 may have wiped them; if gone, that's expected, the persistent unit is the fix. +- Read the current `build-sandbox.sh` first (via SSH `cat` — it's world-readable) to locate the exact `waiting for network` loop and the provisioning block before editing. + +## Abort / rollback +- Rollback = `incus delete --force sandbox-primary sandbox-server01` (rebuildable) and remove any firewall unit you installed (`systemctl disable --now incus-sandbox-firewall; rm` — restores the prior live-rule state). `build-sandbox.sh` edits are in a root file — keep a `.bak` copy before editing so the change is reversible. Nothing production is touched. +- Abort (record + go to wrap-up) if: both containers can't be rebuilt; or the root write to `build-sandbox.sh` needs tier-2 you can't get (defer via manual-auth batch, still deliver the firewall artifacts). + +## Wrap-up notes MUST include: +- Confirmation of each of the 4 contract items (DNS baked + verified on rebuild; provisioning ordering fixed + completes; firewall persistent-mechanism written + whether ENABLED or deferred; both mirrors rebuilt + isolation RE-PROVEN incl. the LAN-DROP test result). +- The incusbr0 subnet/gateway you used. +- A single **MANUAL-AUTH BATCH** = verbatim any privileged command the user must run (e.g. `systemctl enable --now incus-sandbox-firewall.service`), or "none — substrate is fully hardened and self-rebuilding." +- One line: "P1 substrate hardened. Next phase: P2." (or which item blocked + what unblocks it). +``` + +--- + ## P2 — Agent-Sudo service (drop-in sudo-bridge replacement) **Blast radius: NONE while built** (binds 8084; old bridge keeps 8082). `--max-turns 25`.