<< All versions

Skill v1.0.0

currentTrusted Publisher100/100
microsoft/bobsql/build-privatelink-demo
──Details
PublishedSeptember 25, 2026 at 10:32 PM
Content Hashsha256:fd471cbbe9e597eb...
Git SHA
──Files
Files (1 file, 6.5 KB)
SKILL.md6.5 KBactive
SKILL.md · 134 lines · 6.5 KB

version: "1.0.0" name: build-privatelink-demo description: >- Provision, rename, re-region, verify or tear down the Azure environment for DATACON 2026 Demo 3 — "the control plane is the security perimeter" (Private Link + Entra-only Azure SQL Hyperscale + a client VM whose managed identity is the server admin). USE WHEN the presenter says any of: "build the private link demo", "provision demo 3", "set up the control plane demo", "deploy the privatelink demo on this machine", "rebuild demo 3", "move demo 3 to another region", "rename the demo 3 server", "the VM got deallocated, redeploy it", "run pre-flight for demo 3", "why is 05-verify failing", "tear down demo 3", or moves this talk to a new laptop and needs the VNet + VM + Entra-only server + demo kit in place. Scope is PROVISION + CONFIGURE + VERIFY + TEARDOWN ONLY. Do NOT use to present or rehearse the five beats (that's run-privatelink-demo), to build the Adventure Works / SQL MCP kit, or to deploy the Ward General hyperscale talk — those are separate.


Build the Private Link (Demo 3) environment

Read `presentations/dataconus2026/whyazurebest/demos/demo3_controlplane/README.md` first, every time. It is the source of truth and it is current. This skill covers only what the README does not: the order to work in and the traps that have already cost a rebuild.

All paths are workspace-relative to the bwsql root. Kit: presentations/dataconus2026/whyazurebest/demos/demo3_controlplane/.

The shape of it

  • Control plane runs on the laptop, `az` only. The laptop never opens a SQL

connection — it cannot, by design.

  • Data plane runs inside the VM, `sqlsim` only. The VM never runs az.
  • az vm run-command invoke bridges the two through ARM. It keeps working even

after publicNetworkAccess=Disabled, so it is also the way back in if RDP breaks.

Running the scripts

  • Always synchronous, isBackground: false, timeout: 0. Provisioning steps

run minutes. Never background them, never poll.

  • Check the exit code. 05-verify.ps1 exits 1 when the demo is not at Beat 1.
  • Every step is idempotent. If step 4 fails, fix it and run .\setup-all.ps1 -From 4.
  • If the terminal starts mangling chained commands, switch to execution_subagent.

First build on a new machine

powershell
cd presentations/dataconus2026/whyazurebest/demos/demo3_controlplane
.\setup-all.ps1

Steps 1–6: network → VM → RDP rule → Entra-only server + Hyperscale DB → ODBC prerequisites → pre-flight.

Two things need a human:

  1. Step 2 prompts for the VM local administrator password. The presenter types

it straight into the terminal. Never collect it with a question tool, never echo it, never put it in a script or a variable you print.

  1. `sqlsim.exe` must be dragged over RDP into C:\demo — too big for

run-command. setup-all.ps1 pauses and prints the exact source path. Push the other three files first with .\push-vmkit.ps1, then finish with .\setup-all.ps1 -From 6.

Done when 05-verify.ps1 prints 17/17 PASS and "Demo is in its Beat 1 state".

Renaming or moving to another region

Both are edits to 00-config.ps1 — and to `vmkit/config.ps1`.

push-vmkit.ps1 copies vmkit/config.ps1 verbatim; it is not generated from 00-config.ps1. The FQDN and database name are therefore written down twice and nothing enforces that they match.

This has already broken the demo once. After a re-region the VM-side file still named the deleted server. Every laptop script and all 17 checks passed while query.ps1 on the VM pointed at a server that no longer existed.

Order of work:

  1. Validate the target region has capacity for Standard_E2s_v5 before touching

anything — az vm list-skus --location <region> --size Standard_E2s_v5 and check restrictions is empty, plus vCPU quota for the ESv5 family.

  1. Edit 00-config.ps1 ($Location, $ServerName, $DatabaseName).
  2. Edit vmkit/config.ps1 to match.
  3. .\99-teardown.ps1 -Confirm, then .\setup-all.ps1.
  4. .\push-vmkit.ps1, then verify by side effect:

``powershell . .\00-config.ps1 Invoke-VmScript "Get-Content 'C:\demo\config.ps1' | Select-String 'ServerFqdn|DatabaseName'" ``

Logical server names are globally unique DNS labels — a rename can collide.

Traps that are already settled — do not rediscover them

TrapThe rule
--external-admin-sid for a managed identityApplication (client) ID, never the object ID. The object ID creates cleanly and then every login fails. Never write an appId→objectId fallback
Entra admin assignmentMust happen at server create time. az sql server ad-admin create has no --principal-type, so it cannot declare Application
ODBC Driver 18 returns 1603Install VC++ redist first. The MSI log says Error 1723. Never diagnose an MSI from its exit code
az ... dns-zone-group show on a missing groupReturns exit 0 and `{}`. Invoke-Az maps a property-less object to $null — keep that fix. Verify existence checks by side effect, not by the message
az vm run-command --scripts with a multi-line stringSilently emits nothing. Use Invoke-VmScript, which writes a temp .ps1 and passes @file
Read-Host in an agent-driven terminalReturns empty. 99-teardown.ps1 asks for the database name, so it aborts with exit 1 and deletes nothing. The presenter must run teardown themselves

Teardown

powershell
.\99-teardown.ps1 -Confirm

Scoped on purpose: VM, NIC, disk, public IP, private endpoint, DNS zone and link, logical server, database, VNet, nsg-demo3-client, demo3.rdp. It never deletes the resource group — bwsqlestaterg is shared and Demo 1 counts resources in it. Tearing down drops Demo 1's estate by one logical server and one database, so re-check that workbook if the recording matters.

Azure policy injects NRMS-* NSGs alongside the VNet. Teardown does not remove them and they survive as orphans (subnets: null, networkInterfaces: null). They are harmless. Confirm they are unassociated before proposing deletion, and ask first — the resource group is shared.

Before you change shared state

Provisioning is fine to do. Do not, without asking:

  • re-run a beat script that locks the server down, or leave

publicNetworkAccess=Disabled behind after an investigation

  • delete anything in bwsqlestaterg that this kit did not create
  • re-measure by mutating the live environment when the presenter is rehearsing

Leave the environment at Beat 1, 17/17 PASS.

All versions