{
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.13.0"
    },
    "blog_metadata": {
      "topic": "If You’re Standardizing on Azure for AI, Trusted Launch by Default Should Change Your Baseline Architecture",
      "slug": "if-you-re-standardizing-on-azure-for-ai-trusted-launch-by-de",
      "generated_by": "LinkedIn Post Generator + Azure OpenAI",
      "generated_at": "2026-08-06T16:40:43.227Z"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# If You’re Standardizing on Azure for AI, Trusted Launch by Default Should Change Your Baseline Architecture\n",
        "\n",
        "This notebook turns the blog post into a hands-on validation workflow for Azure VM baseline governance. It focuses on Trusted Launch by Default as a landing-zone decision, then demonstrates inventory, drift detection, exception handling, and review summaries using runnable Python examples."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "%pip install pandas"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "import csv\n",
        "from io import StringIO\n",
        "from collections import Counter\n",
        "import pandas as pd"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Baseline control flow\n",
        "\n",
        "The blog frames Trusted Launch by Default as a control-flow decision, not a per-VM checkbox. This cell renders the baseline decision path as structured data so you can validate the architecture sequence programmatically."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "flow_edges = [\n",
        "    (\"AI workload lands on Azure\", \"Baseline decision\"),\n",
        "    (\"Baseline decision\", \"Trusted Launch default\"),\n",
        "    (\"Trusted Launch default\", \"Gen2 image required\"),\n",
        "    (\"Trusted Launch default\", \"Secure Boot enabled\"),\n",
        "    (\"Trusted Launch default\", \"vTPM enabled\"),\n",
        "    (\"Gen2 image required\", \"Golden image catalog check\"),\n",
        "    (\"Secure Boot enabled\", \"Policy / exception review\"),\n",
        "    (\"vTPM enabled\", \"Policy / exception review\"),\n",
        "    (\"Golden image catalog check\", \"Approved baseline\"),\n",
        "    (\"Policy / exception review\", \"Approved baseline\"),\n",
        "    (\"Approved baseline\", \"Deploy or remediate\"),\n",
        "]\n",
        "\n",
        "flow_df = pd.DataFrame(flow_edges, columns=[\"from\", \"to\"])\n",
        "print(flow_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Compare exported VM inventory to an approved golden-image catalog\n",
        "\n",
        "This example reproduces the blog's core drift-report pattern. It compares VM inventory rows against an approved catalog using publisher, offer, SKU, and security type, then emits a review-required report for anything outside the approved baseline."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# Compare exported VM inventory to an approved golden-image catalog and emit a drift report.\n",
        "import csv\n",
        "from io import StringIO\n",
        "\n",
        "inventory_csv = \"\"\"subscription,resource_group,name,publisher,offer,sku,version,security_type\n",
        "sub1,rg-ai,vm-a,Canonical,0001-com-ubuntu-server-jammy,22_04-lts-gen2,latest,TrustedLaunch\n",
        "sub1,rg-ai,vm-b,MicrosoftWindowsServer,WindowsServer,2019-datacenter,latest,Standard\n",
        "sub2,rg-ml,vm-c,Canonical,0001-com-ubuntu-server-jammy,22_04-lts-gen2,latest,TrustedLaunch\n",
        "\"\"\"\n",
        "\n",
        "catalog_csv = \"\"\"publisher,offer,sku,security_type\n",
        "Canonical,0001-com-ubuntu-server-jammy,22_04-lts-gen2,TrustedLaunch\n",
        "MicrosoftWindowsServer,WindowsServer,2022-datacenter-azure-edition,TrustedLaunch\n",
        "\"\"\"\n",
        "\n",
        "approved = {\n",
        "    (r[\"publisher\"], r[\"offer\"], r[\"sku\"], r[\"security_type\"])\n",
        "    for r in csv.DictReader(StringIO(catalog_csv))\n",
        "}\n",
        "rows = list(csv.DictReader(StringIO(inventory_csv)))\n",
        "\n",
        "drift = [\n",
        "    r for r in rows\n",
        "    if (r[\"publisher\"], r[\"offer\"], r[\"sku\"], r[\"security_type\"]) not in approved\n",
        "]\n",
        "\n",
        "output = []\n",
        "for r in drift:\n",
        "    row = {\n",
        "        \"subscription\": r[\"subscription\"],\n",
        "        \"resource_group\": r[\"resource_group\"],\n",
        "        \"name\": r[\"name\"],\n",
        "        \"publisher\": r[\"publisher\"],\n",
        "        \"offer\": r[\"offer\"],\n",
        "        \"sku\": r[\"sku\"],\n",
        "        \"security_type\": r[\"security_type\"],\n",
        "        \"status\": \"REVIEW_REQUIRED\",\n",
        "    }\n",
        "    output.append(row)\n",
        "\n",
        "report_df = pd.DataFrame(output)\n",
        "print(\"Drift report:\")\n",
        "print(report_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Inventory collection pattern across subscriptions\n",
        "\n",
        "The original post includes a PowerShell example using Az modules. In this notebook, the same idea is modeled in Python with sample VM records so you can validate the inventory shape needed for baseline classification without requiring live Azure access."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# Simulate collection of VM image-reference and security metadata across subscriptions for baseline classification.\n",
        "subscription_ids = [\"00000000-0000-0000-0000-000000000001\"]\n",
        "\n",
        "sample_vms = [\n",
        "    {\n",
        "        \"SubscriptionId\": subscription_ids[0],\n",
        "        \"ResourceGroup\": \"rg-ai\",\n",
        "        \"Name\": \"vm-a\",\n",
        "        \"Location\": \"eastus\",\n",
        "        \"Publisher\": \"Canonical\",\n",
        "        \"Offer\": \"0001-com-ubuntu-server-jammy\",\n",
        "        \"Sku\": \"22_04-lts-gen2\",\n",
        "        \"Version\": \"latest\",\n",
        "        \"SecurityType\": \"TrustedLaunch\",\n",
        "        \"SecureBoot\": True,\n",
        "        \"VTpm\": True,\n",
        "        \"PowerState\": \"VM running\",\n",
        "    },\n",
        "    {\n",
        "        \"SubscriptionId\": subscription_ids[0],\n",
        "        \"ResourceGroup\": \"rg-app\",\n",
        "        \"Name\": \"vm-b\",\n",
        "        \"Location\": \"eastus2\",\n",
        "        \"Publisher\": \"MicrosoftWindowsServer\",\n",
        "        \"Offer\": \"WindowsServer\",\n",
        "        \"Sku\": \"2019-datacenter\",\n",
        "        \"Version\": \"latest\",\n",
        "        \"SecurityType\": \"Standard\",\n",
        "        \"SecureBoot\": False,\n",
        "        \"VTpm\": False,\n",
        "        \"PowerState\": \"VM deallocated\",\n",
        "    },\n",
        "]\n",
        "\n",
        "inventory_df = pd.DataFrame(sample_vms)\n",
        "inventory_path = \"vm-baseline-inventory.csv\"\n",
        "inventory_df.to_csv(inventory_path, index=False)\n",
        "print(f\"Saved inventory to {inventory_path}\")\n",
        "print(inventory_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Review workflow sequence\n",
        "\n",
        "This sequence captures the operating model behind the inventory and catalog comparison process. It shows how platform operations export metadata, compare it to the approved catalog, and submit drift findings for remediation or exception review."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "sequence_steps = [\n",
        "    {\"actor\": \"Platform Ops\", \"action\": \"Export VM metadata\", \"target\": \"VM Inventory Export\"},\n",
        "    {\"actor\": \"Platform Ops\", \"action\": \"Load approved images\", \"target\": \"Golden Image Catalog\"},\n",
        "    {\"actor\": \"VM Inventory Export\", \"action\": \"Provide current publisher/offer/sku/security\", \"target\": \"Platform Ops\"},\n",
        "    {\"actor\": \"Golden Image Catalog\", \"action\": \"Provide approved baseline set\", \"target\": \"Platform Ops\"},\n",
        "    {\"actor\": \"Platform Ops\", \"action\": \"Submit drift report\", \"target\": \"Review Board\"},\n",
        "    {\"actor\": \"Review Board\", \"action\": \"Approve remediation or exception\", \"target\": \"Platform Ops\"},\n",
        "]\n",
        "\n",
        "sequence_df = pd.DataFrame(sequence_steps)\n",
        "print(sequence_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Classify VMs into baseline, drift, and exception buckets\n",
        "\n",
        "This example extends the simple catalog comparison by also checking Secure Boot and vTPM state. It produces the three operational buckets emphasized in the post: baseline-compliant, approved-exception, and drift."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# Classify VMs into baseline, drift, and exception buckets from a CSV inventory export.\n",
        "import csv\n",
        "from io import StringIO\n",
        "\n",
        "data = \"\"\"name,publisher,offer,sku,security_type,secure_boot,vtpm,exception_id\n",
        "vm-a,Canonical,0001-com-ubuntu-server-jammy,22_04-lts-gen2,TrustedLaunch,True,True,\n",
        "vm-b,MicrosoftWindowsServer,WindowsServer,2019-datacenter,Standard,False,False,EX-104\n",
        "vm-c,Canonical,0001-com-ubuntu-server-jammy,22_04-lts-gen2,TrustedLaunch,True,False,\n",
        "\"\"\"\n",
        "\n",
        "approved = {(\"Canonical\", \"0001-com-ubuntu-server-jammy\", \"22_04-lts-gen2\", \"TrustedLaunch\")}\n",
        "results = []\n",
        "for row in csv.DictReader(StringIO(data)):\n",
        "    key = (row[\"publisher\"], row[\"offer\"], row[\"sku\"], row[\"security_type\"])\n",
        "    if row[\"exception_id\"]:\n",
        "        bucket = \"approved-exception\"\n",
        "    elif key in approved and row[\"secure_boot\"] == \"True\" and row[\"vtpm\"] == \"True\":\n",
        "        bucket = \"baseline-compliant\"\n",
        "    else:\n",
        "        bucket = \"drift\"\n",
        "    results.append({\"name\": row[\"name\"], \"bucket\": bucket})\n",
        "\n",
        "results_df = pd.DataFrame(results)\n",
        "print(results_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Flag non-Trusted-Launch or non-Gen2 candidates for remediation planning\n",
        "\n",
        "The post also highlights the need to identify workloads that cannot yet meet the new baseline. This Python version evaluates Hyper-V generation, security type, Secure Boot, and vTPM to mark candidates that need review."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# Flag non-Trusted-Launch or non-Gen2 candidates for remediation planning.\n",
        "inventory = [\n",
        "    {\"Name\": \"vm-a\", \"HyperVGeneration\": \"V2\", \"SecurityType\": \"TrustedLaunch\", \"SecureBoot\": True, \"VTpm\": True},\n",
        "    {\"Name\": \"vm-b\", \"HyperVGeneration\": \"V1\", \"SecurityType\": \"Standard\", \"SecureBoot\": False, \"VTpm\": False},\n",
        "    {\"Name\": \"vm-c\", \"HyperVGeneration\": \"V2\", \"SecurityType\": \"TrustedLaunch\", \"SecureBoot\": True, \"VTpm\": False},\n",
        "]\n",
        "\n",
        "review_rows = []\n",
        "for vm in inventory:\n",
        "    needs_review = (\n",
        "        vm[\"HyperVGeneration\"] != \"V2\"\n",
        "        or vm[\"SecurityType\"] != \"TrustedLaunch\"\n",
        "        or not vm[\"SecureBoot\"]\n",
        "        or not vm[\"VTpm\"]\n",
        "    )\n",
        "    review_rows.append({**vm, \"NeedsReview\": needs_review})\n",
        "\n",
        "review_df = pd.DataFrame(review_rows)\n",
        "print(review_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Build a concise platform-review summary from a drift report\n",
        "\n",
        "This example summarizes drift findings by security type and SKU. The goal is to turn raw review-required rows into a small set of patterns that platform, security, and architecture teams can act on during governance reviews."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# Build a concise platform-review summary from a drift report.\n",
        "import csv\n",
        "from collections import Counter\n",
        "from io import StringIO\n",
        "\n",
        "drift_csv = \"\"\"subscription,name,security_type,sku,status\n",
        "sub1,vm-b,Standard,2019-datacenter,REVIEW_REQUIRED\n",
        "sub2,vm-c,TrustedLaunch,22_04-lts-gen2,REVIEW_REQUIRED\n",
        "sub2,vm-d,Standard,2016-datacenter,REVIEW_REQUIRED\n",
        "\"\"\"\n",
        "\n",
        "rows = list(csv.DictReader(StringIO(drift_csv)))\n",
        "by_security = Counter(r[\"security_type\"] for r in rows)\n",
        "by_sku = Counter(r[\"sku\"] for r in rows)\n",
        "\n",
        "print(f\"Total drifted VMs: {len(rows)}\")\n",
        "print(\"By security type:\", dict(by_security))\n",
        "print(\"Top SKUs needing review:\", by_sku.most_common(3))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Join inventory with an approved image catalog to identify drift and exceptions\n",
        "\n",
        "This final validation pattern combines approved catalog matching with exception awareness. It produces the three governance states used throughout the post: Compliant, ApprovedException, and Drift."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {},
      "source": [
        "# Join collected VM inventory with an approved image catalog to identify drift and exceptions.\n",
        "catalog = [\n",
        "    {\"Publisher\": \"Canonical\", \"Offer\": \"0001-com-ubuntu-server-jammy\", \"Sku\": \"22_04-lts-gen2\", \"SecurityType\": \"TrustedLaunch\"},\n",
        "    {\"Publisher\": \"MicrosoftWindowsServer\", \"Offer\": \"WindowsServer\", \"Sku\": \"2022-datacenter-azure-edition\", \"SecurityType\": \"TrustedLaunch\"},\n",
        "]\n",
        "\n",
        "inventory = [\n",
        "    {\"Name\": \"vm-a\", \"Publisher\": \"Canonical\", \"Offer\": \"0001-com-ubuntu-server-jammy\", \"Sku\": \"22_04-lts-gen2\", \"SecurityType\": \"TrustedLaunch\", \"ExceptionId\": \"\"},\n",
        "    {\"Name\": \"vm-b\", \"Publisher\": \"MicrosoftWindowsServer\", \"Offer\": \"WindowsServer\", \"Sku\": \"2019-datacenter\", \"SecurityType\": \"Standard\", \"ExceptionId\": \"EX-104\"},\n",
        "    {\"Name\": \"vm-c\", \"Publisher\": \"MicrosoftWindowsServer\", \"Offer\": \"WindowsServer\", \"Sku\": \"2019-datacenter\", \"SecurityType\": \"Standard\", \"ExceptionId\": \"\"},\n",
        "]\n",
        "\n",
        "approved_keys = {\n",
        "    f'{item[\"Publisher\"]}|{item[\"Offer\"]}|{item[\"Sku\"]}|{item[\"SecurityType\"]}'\n",
        "    for item in catalog\n",
        "}\n",
        "\n",
        "joined = []\n",
        "for item in inventory:\n",
        "    key = f'{item[\"Publisher\"]}|{item[\"Offer\"]}|{item[\"Sku\"]}|{item[\"SecurityType\"]}'\n",
        "    status = \"ApprovedException\" if item[\"ExceptionId\"] else (\"Compliant\" if key in approved_keys else \"Drift\")\n",
        "    joined.append({\"Name\": item[\"Name\"], \"Status\": status, \"ExceptionId\": item[\"ExceptionId\"]})\n",
        "\n",
        "joined_df = pd.DataFrame(joined)\n",
        "print(joined_df.to_string(index=False))"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Summary\n",
        "\n",
        "This notebook validated the blog's main argument: Trusted Launch by Default should be treated as a landing-zone baseline decision, not a discretionary VM setting. The examples showed how to model the control flow, collect inventory, compare deployed VMs to an approved image catalog, classify exceptions, and summarize drift for platform review.\n",
        "\n",
        "## Next Steps\n",
        "\n",
        "1. Replace the sample inventory with exports from your Azure estate.\n",
        "2. Define and version an approved Gen2 + Trusted Launch image catalog.\n",
        "3. Add exception metadata with owner, review date, and exit plan.\n",
        "4. Run the drift and summary cells on a weekly cadence.\n",
        "5. Use the outputs to move from observe, to remediate, to enforce for new deployments."
      ]
    }
  ]
}