diff --git a/__tests__/apps.test.ts b/__tests__/apps.test.ts index 0f92ed1..56b657b 100644 --- a/__tests__/apps.test.ts +++ b/__tests__/apps.test.ts @@ -65,6 +65,19 @@ describe("each app should have a valid config.json", async () => { } }) +describe("n8n-sandbox installation secrets", () => { + test("exposes the shared API key as a password field", async () => { + const fileContent = await getFile('n8n-sandbox', 'config.json') + const config = JSON.parse(fileContent || '{}') + const apiKey = config.form_fields?.find((field: { env_variable?: string }) => field.env_variable === 'SANDBOX_API_KEYS') + + expect(apiKey?.type).toBe('password') + expect(apiKey?.required).toBe(true) + expect(apiKey?.min).toBeGreaterThanOrEqual(48) + expect(config.tipi_version).toBeGreaterThanOrEqual(2) + }) +}) + describe("modern compose files preserve runtime semantics", () => { test("n8n-sandbox keeps its one-shot certificate service", async () => { const fileContent = await getFile('n8n-sandbox', 'docker-compose.yml') @@ -74,6 +87,8 @@ describe("modern compose files preserve runtime semantics", () => { expect(parsed['x-runtipi']?.schema_version).toBe(2) expect(parsed.services?.['sandbox-certs']?.restart).toBe('no') expect(parsed.services?.['sandbox-api']?.['x-runtipi']?.is_main).toBe(true) + expect(parsed.services?.['sandbox-runner-1']?.environment?.SANDBOX_RUNNER_HTTP_BASE_URL).toBe('https://sandbox-runner-1:8080') + expect(parsed.services?.['sandbox-runner-1']?.healthcheck?.test).toContain('https://localhost:8080/readyz') }) }) diff --git a/apps/n8n-sandbox/config.json b/apps/n8n-sandbox/config.json index 862594a..199d22d 100644 --- a/apps/n8n-sandbox/config.json +++ b/apps/n8n-sandbox/config.json @@ -6,7 +6,7 @@ "no_gui": true, "dynamic_config": true, "port": 8080, - "tipi_version": 1, + "tipi_version": 2, "min_tipi_version": "4.7.0", "version": "1.3.0", "author": "n8n", @@ -18,11 +18,11 @@ "supported_architectures": ["amd64", "arm64"], "form_fields": [ { - "type": "random", - "encoding": "hex", + "type": "password", "min": 48, - "label": "Cle API sandbox (SANDBOX_API_KEYS)", - "hint": "A recopier dans l'app n8n : N8N_SANDBOX_SERVICE_API_KEY. Plusieurs cles possibles, separees par des virgules.", + "max": 128, + "label": "Clé API partagée avec n8n (SANDBOX_API_KEYS)", + "hint": "Choisir une clé forte, puis recopier cette même valeur dans N8N_SANDBOX_SERVICE_API_KEY dans les paramètres de l'app n8n officielle.", "required": true, "env_variable": "SANDBOX_API_KEYS" }, diff --git a/apps/n8n-sandbox/docker-compose.yml b/apps/n8n-sandbox/docker-compose.yml index 9992c1c..d5b58d6 100644 --- a/apps/n8n-sandbox/docker-compose.yml +++ b/apps/n8n-sandbox/docker-compose.yml @@ -115,11 +115,10 @@ services: SANDBOX_RUNNER_REGISTRATION_TOKEN: "${SANDBOX_REGISTRATION_TOKEN}" SANDBOX_RUNNER_API_GRPC_ADDR: sandbox-api:9090 - # http:// et non https:// : le mTLS ne couvre que le gRPC - # (enregistrement + SandboxControl). Le trafic proxy exec/files de - # l'API vers le runner reste en HTTP clair authentifie par X-Api-Key - # (docs/configuration.md du depot et compose officiel n8n). - SANDBOX_RUNNER_HTTP_BASE_URL: http://sandbox-runner-1:8080 + # Le listener HTTP du runner sert obligatoirement TLS avec le certificat + # SandboxControl. Son SAN sandbox-runner-1 est genere par sandbox-certs. + # HTTP est refuse depuis la version 1.3.0 pour ne pas exposer X-Api-Key. + SANDBOX_RUNNER_HTTP_BASE_URL: https://sandbox-runner-1:8080 SANDBOX_RUNNER_CONTROL_GRPC_LISTEN_ADDR: ":9091" SANDBOX_RUNNER_CONTROL_GRPC_ADVERTISE_ADDR: sandbox-runner-1:9091 @@ -148,8 +147,9 @@ services: healthcheck: # /readyz passe au vert une fois le runner enregistre aupres de l'API - # (meme check que le compose du depot upstream). - test: "wget -qO- http://localhost:8080/readyz" + # Le probe local ignore uniquement la verification du certificat ; le + # trafic API -> runner reste verifie avec la CA et le SAN partages. + test: "wget -qO- --no-check-certificate https://localhost:8080/readyz" interval: 5s timeout: 5s retries: 24 diff --git a/apps/n8n-sandbox/metadata/description.md b/apps/n8n-sandbox/metadata/description.md index 022b1cb..f38275f 100644 --- a/apps/n8n-sandbox/metadata/description.md +++ b/apps/n8n-sandbox/metadata/description.md @@ -10,7 +10,7 @@ Sandbox auto-hébergé pour l'**AI Assistant** de n8n (setup « Self-host the sa ## Après l'installation -Dans l'app **n8n** (paramètres ou `app.env`), ajouter : +Lors de l'installation, choisir une clé forte dans le champ **Clé API partagée avec n8n**. Dans l'app officielle **n8n** (paramètres ou `app.env`), ajouter le bloc suivant en recopiant cette même clé : ``` N8N_ENABLED_MODULES=instance-ai @@ -18,7 +18,8 @@ N8N_INSTANCE_AI_SANDBOX_ENABLED=true N8N_INSTANCE_AI_SANDBOX_PROVIDER=n8n-sandbox N8N_INSTANCE_AI_SANDBOX_IMAGE=n8nio/n8n-sandbox-service-sandbox:1.3.0 N8N_SANDBOX_SERVICE_URL=http://sandbox-api:8080 -N8N_SANDBOX_SERVICE_API_KEY= +N8N_SANDBOX_SERVICE_API_KEY= +N8N_PROXY_HOPS=1 ``` Puis redémarrer n8n et vérifier depuis son conteneur :