From f539bcbba457d848a94019c573b0e89610c3ec6a Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Tue, 3 Feb 2026 08:45:04 -0500 Subject: [PATCH] docs(07): create phase plan for Socket Security Phase 07: Socket Security - 3 plan(s) in 2 wave(s) - Wave 1: 07-01 (deploy proxy - checkpoint) - Wave 2: 07-02 (migrate workflow), 07-03 (verify blocking) - parallel - Ready for execution Co-Authored-By: Claude Opus 4.5 --- .planning/ROADMAP.md | 11 +- .../phases/07-socket-security/07-01-PLAN.md | 139 ++++++++++++++++ .../phases/07-socket-security/07-02-PLAN.md | 148 ++++++++++++++++++ .../phases/07-socket-security/07-03-PLAN.md | 136 ++++++++++++++++ 4 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 .planning/phases/07-socket-security/07-01-PLAN.md create mode 100644 .planning/phases/07-socket-security/07-02-PLAN.md create mode 100644 .planning/phases/07-socket-security/07-03-PLAN.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 71051f1..ec17afe 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -40,6 +40,13 @@ Plans: **Requirements:** SEC-01, SEC-02, SEC-03, SEC-04 +**Plans:** 3 plans + +Plans: +- [ ] 07-01-PLAN.md — Deploy docker-socket-proxy via Unraid CA +- [ ] 07-02-PLAN.md — Migrate workflow curl commands to proxy +- [ ] 07-03-PLAN.md — Verify dangerous APIs are blocked + **Success Criteria:** 1. Socket proxy container runs on internal network with Docker socket mounted 2. n8n container connects to proxy via TCP instead of mounting docker.sock directly @@ -101,8 +108,8 @@ Plans: | Phase | Name | Requirements | Status | |-------|------|--------------|--------| -| 6 | n8n API Access | API-01, API-02, API-03, API-04 | Complete ✓ | -| 7 | Socket Security | SEC-01, SEC-02, SEC-03, SEC-04 | Pending | +| 6 | n8n API Access | API-01, API-02, API-03, API-04 | Complete | +| 7 | Socket Security | SEC-01, SEC-02, SEC-03, SEC-04 | Planned | | 8 | Inline Keyboard Infrastructure | KEY-01, KEY-02, KEY-03, KEY-04, KEY-05 | Pending | | 9 | Batch Operations | BAT-01, BAT-02, BAT-03, BAT-04, BAT-05, BAT-06 | Pending | | 10 | Polish & Audit | UNR-01, ENV-01, ENV-02 | Pending | diff --git a/.planning/phases/07-socket-security/07-01-PLAN.md b/.planning/phases/07-socket-security/07-01-PLAN.md new file mode 100644 index 0000000..24ad8c7 --- /dev/null +++ b/.planning/phases/07-socket-security/07-01-PLAN.md @@ -0,0 +1,139 @@ +--- +phase: 07-socket-security +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: [] +autonomous: false + +user_setup: + - service: docker-socket-proxy + why: "Filtered Docker API access for n8n" + dashboard_config: + - task: "Install docker-socket-proxy from Unraid Community Apps" + location: "Unraid Apps tab > Search 'dockersocket'" + - task: "Configure environment variables" + location: "Container settings" + - task: "Add proxy to n8n's Docker network" + location: "Container network settings" + +must_haves: + truths: + - "docker-socket-proxy container is running" + - "Proxy is on same Docker network as n8n" + - "Proxy has Docker socket mounted" + artifacts: + - path: "docker-socket-proxy container" + provides: "HAProxy-based Docker API filtering" + contains: "CONTAINERS=1, IMAGES=1, POST=1, ALLOW_START=1, ALLOW_STOP=1, ALLOW_RESTARTS=1" + key_links: + - from: "n8n container" + to: "docker-socket-proxy:2375" + via: "Docker network DNS" + pattern: "same custom bridge network" +--- + + +Deploy docker-socket-proxy container via Unraid Community Apps. + +Purpose: Establish the proxy infrastructure that n8n will connect to instead of direct Docker socket access. This is the foundation that Plan 02 will wire up. +Output: Running docker-socket-proxy container with correct environment variables and network configuration. + + + +@/home/luc/.claude/get-shit-done/workflows/execute-plan.md +@/home/luc/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/07-socket-security/07-CONTEXT.md +@.planning/phases/07-socket-security/07-RESEARCH.md + + + + + + Task 1: Install and Configure docker-socket-proxy + + User must install docker-socket-proxy via Unraid Community Apps UI. + + **Steps:** + 1. Open Unraid web UI > Apps tab + 2. Search for "dockersocket" (tecnativa/docker-socket-proxy template) + 3. Click Install + 4. Configure the following settings: + + **Container Name:** docker-socket-proxy + + **Environment Variables (enable these):** + - CONTAINERS=1 (enable /containers/* endpoints) + - IMAGES=1 (enable /images/* endpoints - needed for update command) + - POST=1 (enable POST/PUT/DELETE operations) + - ALLOW_START=1 (enable start action) + - ALLOW_STOP=1 (enable stop action) + - ALLOW_RESTARTS=1 (enable restart action) + + **Keep defaults (already 0/disabled):** + - BUILD=0 + - COMMIT=0 + - EXEC=0 + - SECRETS=0 + - AUTH=0 + + **Network Configuration:** + - Find n8n's custom network name (check n8n container settings) + - Add docker-socket-proxy to that same network + + 5. Click Apply to create the container + 6. Verify container is running (green status) + + + Provide the following information to continue: + 1. Container name (should be "docker-socket-proxy") + 2. Docker network name that both n8n and proxy are on + 3. Confirm container is running + + docker-socket-proxy container is running on same network as n8n + Provide: container name, network name, and confirm running status + + + + Task 2: Verify Proxy Connectivity + None (verification only) + + Using the n8n API, test that the proxy is reachable from n8n's perspective. + + 1. Use n8n API to get workflow and find an Execute Command node + 2. Test proxy connectivity by checking if n8n can resolve docker-socket-proxy hostname + 3. Make a test API call through the proxy to list containers + + If proxy is not reachable, the network configuration needs adjustment. + + + Run curl from n8n to proxy: `curl -s 'http://docker-socket-proxy:2375/v1.47/containers/json?all=true'` should return container list JSON + + n8n can reach docker-socket-proxy:2375 and receive valid Docker API responses + + + + + +1. docker-socket-proxy container is running in Unraid +2. Container has correct environment variables (CONTAINERS=1, IMAGES=1, POST=1, ALLOW_START=1, ALLOW_STOP=1, ALLOW_RESTARTS=1) +3. Proxy is on the same Docker network as n8n +4. n8n can reach docker-socket-proxy:2375 + + + +- docker-socket-proxy container running with correct config +- n8n and proxy share a Docker network +- Test curl from n8n to proxy returns container list + + + +After completion, create `.planning/phases/07-socket-security/07-01-SUMMARY.md` + diff --git a/.planning/phases/07-socket-security/07-02-PLAN.md b/.planning/phases/07-socket-security/07-02-PLAN.md new file mode 100644 index 0000000..4e3cb7f --- /dev/null +++ b/.planning/phases/07-socket-security/07-02-PLAN.md @@ -0,0 +1,148 @@ +--- +phase: 07-socket-security +plan: 02 +type: execute +wave: 2 +depends_on: ["07-01"] +files_modified: [n8n-workflow.json] +autonomous: false + +must_haves: + truths: + - "All bot commands work through proxy (status, start, stop, restart, update, logs)" + - "n8n no longer references direct Docker socket in curl commands" + - "Dangerous API calls return blocked error message" + artifacts: + - path: "n8n-workflow.json" + provides: "Updated n8n workflow using proxy instead of direct socket" + contains: "docker-socket-proxy:2375" + key_links: + - from: "n8n Execute Command nodes" + to: "docker-socket-proxy:2375" + via: "TCP curl calls" + pattern: "curl.*docker-socket-proxy:2375" +--- + + +Migrate all n8n workflow curl commands from direct Docker socket to proxy. + +Purpose: Route all Docker API calls through the filtered proxy, removing direct socket access from n8n. +Output: Updated n8n-workflow.json with all 16 curl commands migrated to use proxy endpoint. + + + +@/home/luc/.claude/get-shit-done/workflows/execute-plan.md +@/home/luc/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/07-socket-security/07-CONTEXT.md +@.planning/phases/07-socket-security/07-RESEARCH.md +@.planning/phases/07-socket-security/07-01-SUMMARY.md +@n8n-workflow.json + + + + + + Task 1: Update Workflow Curl Commands + n8n-workflow.json + + Replace all Docker socket curl commands with proxy TCP calls. + + **Search and Replace Pattern:** + FROM: `--unix-socket /var/run/docker.sock 'http://localhost/` + TO: `--max-time 5 'http://docker-socket-proxy:2375/` + + **Commands to update (16 total):** + 1. Container list: `curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.47/containers/json?all=true'` + 2. Container inspect: Uses template `http://localhost/v1.47/containers/${containerId}/json` + 3. Image inspect: Uses template `http://localhost/v1.47/images/${imageName}/json` + 4. Image pull: Uses template with POST to `images/create?fromImage=` + 5. Start/stop/restart: Uses template `containers/${containerId}/${action}` + 6. Container delete: Uses template `containers/${containerId}` with DELETE + 7. Container create: Uses POST with JSON body to `containers/create` + 8. Container logs: Uses `containers/${containerId}/logs` + + **Also update error handling in JavaScript nodes:** + - Add handling for HTTP 403 responses: "This action is blocked by security policy" + - Distinguish between 403 (blocked) and other errors + - Do NOT retry on 403 - fail immediately + + **Do NOT change:** + - API version (/v1.47/) - keep as is for compatibility + - The 600 second timeout on image pull (that's intentional for large images) + - Any non-Docker-socket curl commands + + + 1. `grep -c 'unix-socket.*docker\.sock' n8n-workflow.json` returns 0 + 2. `grep -c 'docker-socket-proxy:2375' n8n-workflow.json` returns 16 (or similar count) + 3. `grep -c 'max-time 5' n8n-workflow.json` shows timeout added (except image pull) + + All Docker socket references replaced with proxy endpoint, timeout added + + + + Task 2: Push Updated Workflow to n8n + n8n-workflow.json + + Use n8n API to update the live workflow with the modified JSON. + + 1. Load .env.n8n-api for API credentials + 2. Read the updated n8n-workflow.json + 3. PUT to /api/v1/workflows/{id} with the updated workflow + 4. Verify the workflow was updated (check updatedAt timestamp) + + **Workflow ID:** HmiXBlJefBRPMS0m4iNYc (from Phase 6 summary) + + + API PUT request returns 200 with updated workflow, updatedAt timestamp is recent + + n8n workflow updated via API with proxy configuration + + + + Task 3: Verify All Bot Commands Work + Updated n8n workflow that routes all Docker API calls through the socket proxy instead of direct socket access + + Test each bot command via Telegram: + + 1. **status** - Should list all containers with their states + 2. **start [container]** - Pick a stopped container, verify it starts + 3. **stop [container]** - Stop that container, verify it stops + 4. **restart [container]** - Restart a container, verify success message + 5. **update [container]** - Update a container (or verify "already up to date" message) + 6. **logs [container]** - View logs for a container + + All commands should work identically to before the proxy migration. + + If any command fails, check: + - Error message (403 = proxy blocking, other = connectivity issue) + - Proxy container logs in Unraid + - Network connectivity between n8n and proxy + + Type "all commands working" or describe which commands failed + + + + + +1. No unix-socket references remain in n8n-workflow.json +2. All curl commands use docker-socket-proxy:2375 +3. Timeouts added to curl commands (except long-running image pull) +4. Error handling includes 403 response handling +5. All 6 bot commands work via Telegram + + + +- Zero unix-socket references in workflow +- All bot commands functional through proxy +- User confirms "all commands working" + + + +After completion, create `.planning/phases/07-socket-security/07-02-SUMMARY.md` + diff --git a/.planning/phases/07-socket-security/07-03-PLAN.md b/.planning/phases/07-socket-security/07-03-PLAN.md new file mode 100644 index 0000000..86adb9c --- /dev/null +++ b/.planning/phases/07-socket-security/07-03-PLAN.md @@ -0,0 +1,136 @@ +--- +phase: 07-socket-security +plan: 03 +type: execute +wave: 2 +depends_on: ["07-01"] +files_modified: [] +autonomous: true + +must_haves: + truths: + - "Exec API endpoint returns 403 Forbidden" + - "Build API endpoint returns 403 Forbidden" + - "Create (new container) API endpoint returns 403 Forbidden" + artifacts: [] + key_links: + - from: "n8n/curl" + to: "docker-socket-proxy:2375" + via: "blocked endpoints" + pattern: "403 Forbidden" +--- + + +Verify that dangerous Docker APIs are blocked by the proxy. + +Purpose: Confirm SEC-03 requirement - socket proxy blocks dangerous APIs (exec, create, build). +Output: Documented proof that blocked endpoints return 403 Forbidden. + + + +@/home/luc/.claude/get-shit-done/workflows/execute-plan.md +@/home/luc/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/07-socket-security/07-CONTEXT.md +@.planning/phases/07-socket-security/07-RESEARCH.md +@.planning/phases/07-socket-security/07-01-SUMMARY.md + + + + + + Task 1: Test Blocked Endpoints Return 403 + None (verification only) + + Test that the proxy correctly blocks dangerous Docker API endpoints. + + **Test each blocked endpoint:** + + 1. **Exec (EXEC=0)** - Attempt to create an exec instance: + ``` + curl -s -o /dev/null -w "%{http_code}" -X POST 'http://docker-socket-proxy:2375/v1.47/containers/[any-container-id]/exec' -H "Content-Type: application/json" -d '{"Cmd":["echo","test"]}' + ``` + Expected: 403 + + 2. **Build (BUILD=0)** - Attempt to build an image: + ``` + curl -s -o /dev/null -w "%{http_code}" -X POST 'http://docker-socket-proxy:2375/v1.47/build' + ``` + Expected: 403 + + 3. **Commit (COMMIT=0)** - Attempt to commit a container: + ``` + curl -s -o /dev/null -w "%{http_code}" -X POST 'http://docker-socket-proxy:2375/v1.47/commit?container=[any-container-id]' + ``` + Expected: 403 + + **Note:** These tests should be run from inside the n8n container to verify the proxy is blocking correctly from the same network context. + + If tests can't be run from n8n directly, document that proxy defaults block these endpoints (tecnativa proxy blocks by default when env vars are 0 or unset). + + + All three blocked endpoints return HTTP 403 status code + + SEC-03 verified: exec, build, and commit endpoints blocked with 403 + + + + Task 2: Document Security Configuration + None (documentation in SUMMARY) + + Document the security posture achieved: + + **Allowed operations:** + - List containers (GET /containers/json) + - Inspect container (GET /containers/{id}/json) + - Start container (POST /containers/{id}/start) + - Stop container (POST /containers/{id}/stop) + - Restart container (POST /containers/{id}/restart) + - Remove container (DELETE /containers/{id}) + - List images (GET /images/json) + - Inspect image (GET /images/{id}/json) + - Pull image (POST /images/create) + - Create container (POST /containers/create) + - Get logs (GET /containers/{id}/logs) + + **Blocked operations:** + - Execute commands inside containers (POST /containers/{id}/exec) + - Build images (POST /build) + - Commit containers to images (POST /commit) + - Manage secrets (POST /secrets/*) + - Authentication operations + + **Security benefit:** + Even if n8n is compromised, an attacker cannot: + - Execute arbitrary commands inside containers (no container escape) + - Build malicious images + - Access Docker secrets + + + Documentation captured in plan summary + + Security posture documented for SEC-03 + + + + + +1. Exec endpoint returns 403 +2. Build endpoint returns 403 +3. Commit endpoint returns 403 +4. Security documentation complete + + + +- All three dangerous endpoints confirmed blocked +- Security posture documented + + + +After completion, create `.planning/phases/07-socket-security/07-03-SUMMARY.md` +