diff --git a/docs/extension.md b/docs/extension.md index 19cb615..7015c44 100644 --- a/docs/extension.md +++ b/docs/extension.md @@ -35,10 +35,22 @@ It exports **only local** settings, even if an old `.env` contains Azure setting into the URI input. That field is **not masked**. Never paste a password-bearing URI there. The generated URI points to `127.0.0.1`, selects your database, and specifies TLS, `SCRAM-SHA-256`, `authSource=admin` and `directConnection=true`. -4. For this loopback connection only, choose **Allow invalid certificates** when - the TLS picker appears. TLS encryption stays **on**; this accepts the existing - local development server's self-signed certificate. It is not “disable TLS,” - not a global setting, and never applies to Azure or another remote service. +4. **In the local TLS prompt, select “Allow invalid certificates” for BOTH + Workshop — Site A and Workshop — Site B. Do not leave “Enable TLS (default)” + selected for these workshop connections.** The default validates certificates + and rejects the development server's self-signed certificate with the error + **“self-signed certificate.”** Keep `tls=true` in the generated URI: encryption + stays **on**; only certificate validation is relaxed for these specific + `127.0.0.1` development connections. Never apply this exception to Azure or + another remote service. + + > **DocumentDB for VS Code 1.0.0 label caveat:** after this choice, the tree or + > dashboard may display **“⚠ TLS/SSL Disabled.”** That wording is misleading + > for this exact workshop configuration: the supplied URI still has `tls=true`, + > and the extension applies `tlsAllowInvalidCertificates=true` rather than + > disabling encryption. Both local connections were exercised successfully + > with this choice in the attendee test. This is not an instruction to set + > `tls=false`, disable TLS globally, or change your database password. 5. If asked for an authentication method, choose **Username and Password** (native authentication). Enter the section's username and paste its password only into the **masked password prompt**. Do not select Microsoft Entra/Azure login. diff --git a/docs/lab.md b/docs/lab.md index 29b523c..f455f30 100644 --- a/docs/lab.md +++ b/docs/lab.md @@ -49,6 +49,14 @@ Neither means managed Azure. Both sites have separate credentials and volumes. Run `npm run extension:connections` and follow the [private setup steps](extension.md#connect-the-two-existing-sites-privately). Save **Workshop — Site A** and **Workshop — Site B** in DocumentDB **Connections**. + +> **Local TLS prompt: choose “Allow invalid certificates” for both sites.** +> The default certificate-validation choice rejects their self-signed development +> certificates. Keep `tls=true`: encryption stays on. Extension 1.0.0 may label +> this **“TLS/SSL Disabled”** even though only certificate validation is relaxed +> for these loopback connections; see the [TLS explanation](extension.md#connect-the-two-existing-sites-privately). +> Do not use this exception for Azure or change global TLS settings. + Expand each to its actual workshop database. This is required lab tooling, not an Azure demo: no sign-in, no **Set Up Local** third database, no forwarded database ports. Keep the credential file out of screen sharing. If the editor is blocked, diff --git a/scripts/extension-connections.mjs b/scripts/extension-connections.mjs index d16caff..9218b8f 100644 --- a/scripts/extension-connections.mjs +++ b/scripts/extension-connections.mjs @@ -105,7 +105,9 @@ export async function writeExtensionConnections(directory = process.cwd(), log = const content = [marker, "SECRET: open privately; never share, commit, screenshot, or paste into a terminal.", "Use DocumentDB: New Connection... > Connection String. No Azure sign-in or local setup wizard.", "Paste only the credential-free URI into the unmasked URI box; username/password go in separate native-auth prompts.", - "Select Allow invalid certificates for these loopback connections only: TLS stays enabled with the local self-signed certificate.", "", + "LOCAL TLS PROMPT (BOTH SITES): choose Allow invalid certificates, not Enable TLS (default). The default rejects the local self-signed certificate.", + "Keep tls=true: encryption stays on. In extension 1.0.0, the warning TLS/SSL Disabled is misleading for this configuration; only certificate validation is relaxed.", + "This exception is only for these 127.0.0.1 development connections. Never apply it to Azure, set tls=false, change global TLS settings, or rotate passwords to fix a certificate error.", "", ...connections.flatMap(({ label, port, database, uri, username, password }) => [label, `Loopback port: ${port}; database: ${database}`, `Connection string (no credentials): ${uri}`, `Username: ${username}`, `Password (paste only in masked prompt): ${password}`, ""]), ].join("\n"); const temporary = join(privateDirectory, `.connections-${randomUUID()}.tmp`); diff --git a/test/extension.test.js b/test/extension.test.js index 5fc9bba..a5c8aa0 100644 --- a/test/extension.test.js +++ b/test/extension.test.js @@ -66,6 +66,10 @@ test("private handoff is owner-only, atomically repeatable, excludes cloud and p assert.equal((await stat(output)).mode & 0o777, 0o600); const content = await readFile(output, "utf8"); assert.match(content, /Password \(paste only in masked prompt\): site A: p@ss\/#\$literal/); + assert.match(content, /LOCAL TLS PROMPT \(BOTH SITES\): choose Allow invalid certificates, not Enable TLS \(default\)/); + assert.match(content, /Keep tls=true: encryption stays on/); + assert.match(content, /TLS\/SSL Disabled is misleading/); + assert.match(content, /Never apply it to Azure/); assert.doesNotMatch(content, /never-export|cloud\.invalid/); assert.doesNotMatch(logs.join("\n"), /mongodb:|p@ss|independent-secret|never-export/); assert.equal(await writeExtensionConnections(directory, () => {}), output); @@ -207,3 +211,15 @@ test("read-only playground templates use the selected database/catalog, bounded assert.equal(calls[0].projection.catalogVersion, 1); assert.equal(calls[0].limit, 5); }); + + +test("attendee guides call out the local TLS choice and misleading v1.0 warning", async () => { + for (const name of ["../docs/extension.md", "../docs/lab.md"]) { + const text = await readFile(new URL(name, import.meta.url), "utf8"); + assert.match(text, /Allow invalid certificates/); + assert.match(text, /self-signed/); + assert.match(text, /tls=true/); + assert.match(text, /TLS\/SSL Disabled/); + assert.match(text, /Azure/); + } +});