From b69bc479350cfe0b0dfcff7bb29a61c1da73db26 Mon Sep 17 00:00:00 2001 From: erjosito Date: Tue, 21 Nov 2023 08:20:28 +0000 Subject: [PATCH] [create-pull-request] automated change --- checklists/checklist.en.master.json | 28496 ++++++++-------- .../network_appdelivery_checklist.en.json | 4 +- .../network_appdelivery_checklist.es.json | 140 +- .../network_appdelivery_checklist.ja.json | 140 +- .../network_appdelivery_checklist.ko.json | 140 +- .../network_appdelivery_checklist.pt.json | 140 +- ...network_appdelivery_checklist.zh-Hant.json | 454 + .../macrofree/checklist.en.master.xlsx | Bin 284940 -> 285547 bytes .../network_appdelivery_checklist.en.xlsx | Bin 23374 -> 23619 bytes .../network_appdelivery_checklist.es.xlsx | Bin 23851 -> 24099 bytes .../network_appdelivery_checklist.ja.xlsx | Bin 24666 -> 24989 bytes .../network_appdelivery_checklist.ko.xlsx | Bin 24437 -> 24702 bytes .../network_appdelivery_checklist.pt.xlsx | Bin 23848 -> 24108 bytes ...network_appdelivery_checklist.zh-Hant.xlsx | Bin 0 -> 24430 bytes .../alz_checklist.en_network_counters.json | 382 +- ...hecklist.en_network_counters_template.json | 2 +- .../alz_checklist.en_network_tabcounters.json | 1826 +- ...klist.en_network_tabcounters_template.json | 2 +- .../alz_checklist.en_network_workbook.json | 340 +- ...hecklist.en_network_workbook_template.json | 2 +- ...livery_checklist.en_counters_workbook.json | 8 +- ...ecklist.en_counters_workbook_template.json | 2 +- ...ork_appdelivery_checklist.en_workbook.json | 6 +- ...livery_checklist.en_workbook_template.json | 2 +- 24 files changed, 16340 insertions(+), 15746 deletions(-) create mode 100644 checklists/network_appdelivery_checklist.zh-Hant.json create mode 100644 spreadsheet/macrofree/network_appdelivery_checklist.zh-Hant.xlsx diff --git a/checklists/checklist.en.master.json b/checklists/checklist.en.master.json index 045225d6d..4a73d8c2d 100644 --- a/checklists/checklist.en.master.json +++ b/checklists/checklist.en.master.json @@ -1,3257 +1,2482 @@ { "items": [ { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "54174158-33fb-43ae-9c2d-e743165c3acb", + "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", "services": [ - "Entra" + "Defender", + "Subscriptions" ], - "severity": "Medium", - "subcategory": "Microsoft Entra ID Tenants", - "text": "Use one Entra tenant for managing your Azure resources, unless you have a clear regulatory or business requirement for multi-tenants.", - "waf": "Operations" + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Security Center/Defender enable in all subscriptions" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "349f0364-d28d-442e-abbb-c868255abc91", + "link": "https://learn.microsoft.com/azure/security-center/enable-azure-defender", "services": [ - "Entra" + "Defender", + "Monitor" ], - "severity": "Low", - "subcategory": "Microsoft Entra ID Tenants", - "text": "Ensure you have a Multi-Tenant Automation approach to managing your Microsoft Entra ID Tenants", - "waf": "Operations" + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Security Center/Defender enabled on all Log Analytics workspaces" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", - "id": "A01.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "64e9a19a-e28c-484c-93b6-b7818ca0e6c4", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/enable-data-collection?tabs=autoprovision-feature#what-event-types-are-stored-for-common-and-minimal", "services": [ - "Entra" + "Defender" ], - "severity": "Low", - "subcategory": "Microsoft Entra ID Tenants", - "text": "Leverage Azure Lighthouse for Multi-Tenant Management", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pricing & Settings", + "text": "Data collection set to 'Common'" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "2149d414-a923-4c35-94d1-1029bd6aaf11", + "link": "https://learn.microsoft.com/azure/security-center/enable-azure-defender", "services": [ - "Entra" + "Defender" ], - "severity": "Medium", - "subcategory": "Cloud Solution Provider", - "text": "Ensure that Azure Lighthouse is used for administering the tenant by partner", - "waf": "Cost" + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Defender for Cloud enhanced security features are all enabled" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", - "id": "A02.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "e6b84ee5-ef43-4d29-a248-1718d5d1f5f7", + "link": "https://learn.microsoft.com/azure/security-center/security-center-enable-data-collection", "services": [ - "Entra" + "Defender", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Cloud Solution Provider", - "text": "Discuss support request and escalation process with CSP partner", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Pricing & Settings", + "text": "Auto-provisioning enabled as per company policy (policy must exist)" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "32952499-58c8-4e6f-ada5-972e67893d55", - "id": "A02.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "25759e35-680e-4782-9ac9-32213d027ff4", + "link": "https://learn.microsoft.com/azure/security-center/security-center-provide-security-contact-details", "services": [ - "Entra", - "Cost" + "Defender", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Cloud Solution Provider", - "text": "Setup Cost Reporting and Views with Azure Cost Management", - "waf": "Cost" + "severity": "Low", + "subcategory": "Pricing & Settings", + "text": "Email notifications enabled as per company policy (policy must exist)" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "12f70993-0631-4583-9ee7-9d6c6d363206", + "link": "https://learn.microsoft.com/azure/security-center/security-center-wdatp?WT.mc_id=Portal-Microsoft_Azure_Security_CloudNativeCompute&tabs=windows", "services": [ - "LoadBalancer", - "Entra" + "Defender" ], "severity": "Medium", - "subcategory": "Enterprise Agreement", - "text": "Configure Notification Contacts to a group mailbox", - "waf": "Cost" + "subcategory": "Pricing & Settings", + "text": "Enable integrations options are selected " }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", - "id": "A03.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "5b7abae4-4aad-45e8-a79e-2e86667313c5", + "link": "https://learn.microsoft.com/azure/security-center/defender-for-container-registries-cicd", "services": [ - "Entra", - "TrafficManager" + "Defender" ], - "severity": "Low", - "subcategory": "Enterprise Agreement", - "text": "Use departments and accounts to map your organization's structure to your enrollment hierarchy which can help with separating billing.", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Pricing & Settings", + "text": "CI/CD integration is configured" }, { - "ammp": true, - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", - "id": "A03.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "05675c5e-985b-4859-a774-f7e371623b87", + "link": "https://learn.microsoft.com/azure/security-center/continuous-export?tabs=azure-portal", "services": [ - "Entra" + "EventHubs", + "Defender" ], "severity": "High", - "subcategory": "Enterprise Agreement", - "text": "Ensure that Accounts are configured to be of the type 'Work or School Account", - "waf": "Security" + "subcategory": "Pricing & Settings", + "text": "Continuous export 'Event Hub' is enabled if using 3rd party SIEM" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", - "id": "A03.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "5a917e1f-349f-4036-9d28-d42e8bbbc868", + "link": "https://learn.microsoft.com/azure/security-center/continuous-export?tabs=azure-portal", "services": [ - "Entra", - "Cost" + "Monitor", + "Sentinel", + "Defender" ], "severity": "Medium", - "subcategory": "Enterprise Agreement", - "text": "Enable both DA View Charges and AO View Charges on your EA Enrollments to allow users with the correct perms review Cost and Billing Data.", - "waf": "Security" + "subcategory": "Pricing & Settings", + "text": "Continuous export 'Log Analytics Workspace' is enabled if not using Azure Sentinel" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", - "id": "A03.05", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "255abc91-64e9-4a19-ae28-c84c43b6b781", + "link": "https://learn.microsoft.com/azure/security-center/quickstart-onboard-aws?WT.mc_id=Portal-Microsoft_Azure_Security", "services": [ - "Subscriptions", - "Entra", - "Cost" + "Defender" ], - "severity": "Low", - "subcategory": "Enterprise Agreement", - "text": "Make use of Enterprise Dev/Test Subscriptions to reduce costs for non-production workloads", - "waf": "Cost" + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Cloud connector enabled for AWS" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", - "id": "A03.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "8ca0e6c4-2149-4d41-9a92-3c3574d11029", + "link": "https://learn.microsoft.com/azure/security-center/quickstart-onboard-gcp", "services": [ - "RBAC", - "Entra" + "Defender" ], - "severity": "Medium", - "subcategory": "Enterprise Agreement", - "text": "Periodically audit the role assignments to review who has access to your Enterprise Agreement Enrollment", - "waf": "Cost" + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Cloud connector enabled for GCP" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "cce9bdf6-b483-45a0-85ec-c8232b230652", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy-integrate-with-microsoft-cloud-application-security", "services": [ - "Entra" + "Defender", + "Entra", + "Monitor" ], "severity": "Low", - "subcategory": "Microsoft Customer Agreement", - "text": "Configure Agreement billing account notification contact email", - "waf": "Cost" + "subcategory": "Pricing & Settings", + "text": "If using Azure AD Application proxy, consider integrating with Microsoft Defender for Cloud Apps to monitor application access in real-time and apply advanced security controls." }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", - "id": "A04.02", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "df9cc234-18db-4611-9126-5f4bb47a393a", + "link": "https://learn.microsoft.com/azure/security-center/secure-score-security-controls", "services": [ - "Entra", - "Storage", - "Cost" + "Defender" ], - "severity": "Low", - "subcategory": "Microsoft Customer Agreement", - "text": "Use Billing Profiles and Invoice sections to structure your agreements billing for effective cost management", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Recommendations", + "text": "All recommendations remediated or disabled if not required." }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", - "id": "A04.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "description": "Microsoft minimum target for all customers is 70%", + "guid": "08032729-4798-4b15-98a2-19a46ceb5443", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", "services": [ - "Entra", - "Cost" + "Defender" ], - "severity": "Low", - "subcategory": "Microsoft Customer Agreement", - "text": "Make use of Azure Plan to reduce costs for non-production workloads", - "waf": "Cost" + "severity": "High", + "subcategory": "Recommendations", + "text": "Security Score>70%" }, { - "category": "Azure Billing and Microsoft Entra ID Tenants", - "checklist": "Azure Landing Zone Review", - "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", - "id": "A04.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "50259226-4429-42bb-9285-37a55119bf8e", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/tutorial-security-incident", "services": [ - "RBAC", - "Entra" + "Monitor", + "Defender" ], "severity": "Medium", - "subcategory": "Microsoft Customer Agreement", - "text": "Periodically audit the agreement billing RBAC role assignments to review who has access to your MCA billing account", - "waf": "Cost" + "subcategory": "Security Alerts", + "text": "Security Alerts contain only those generated in the past 24 hours (remediate or disable older security alerts)" }, { - "ammp": true, - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "4348bf81-7573-4512-8f46-9061cc198fea", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "8f585428-7d9c-4dc1-96cd-072af9b141a8", + "link": "https://learn.microsoft.com/azure/security-center/custom-dashboards-azure-workbooks", "services": [ - "Entra" + "Defender" ], - "severity": "High", - "subcategory": "Microsoft Entra ID and Hybrid Identity", - "text": "Use managed identities instead of service principals for authentication to Azure services", - "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", - "waf": "Security" + "severity": "Medium", + "subcategory": "Workbooks", + "text": "If continuous export is enabled, default workbooks published to custom security dashboard" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", - "id": "B02.01", - "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "98a535e7-3789-47e7-8ca7-da7be9962a15", + "link": "https://techcommunity.microsoft.com/t5/microsoft-defender-for-cloud/bd-p/MicrosoftDefenderCloud", "services": [ - "ASR", - "Entra" + "Defender" ], "severity": "Medium", - "subcategory": "Microsoft Entra ID", - "text": "When deploying an AD Connect VM, consider having a staging sever for high availability / Disaster recovery", - "waf": "Reliability" + "subcategory": "Community", + "text": "Customer is aware of the value of the 'Community' page and has a regular cadence set up to review" }, { - "ammp": true, - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "984a859c-773e-47d2-9162-3a765a917e1f", - "id": "B03.01", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "description": "Customer Operational best practice - Transparency", + "guid": "93846da9-7cc3-4923-856b-22586f4a1641", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/enable-enhanced-security", "services": [ - "Entra" + "Defender", + "Subscriptions" ], "severity": "High", - "subcategory": "Identity", - "text": "Implement an emergency access or break-glass accounts to prevent tenant-wide account lockout", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", - "waf": "Security" + "subcategory": "Secure Score", + "text": "All subscriptions protected by Security Center are shown (no subscription filter set)" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", - "id": "B03.02", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "bdddea8a-487c-4deb-9861-bc3bc14aea6e", + "link": "https://learn.microsoft.com/azure/security-center/security-center-compliance-dashboard", "services": [ - "Entra", - "Monitor" + "Defender" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Integrate Microsoft Entra ID logs with the platform-central Azure Monitor. Azure Monitor allows for a single source of truth around log and monitoring data in Azure, giving organizations a cloud native options to meet requirements around log collection and retention.", - "waf": "Security" + "severity": "High", + "subcategory": "Regulatory Compliance", + "text": "Compliance controls are green for any required compliance requirements" }, { - "ammp": true, - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "348ef254-c27d-442e-abba-c7571559ab91", - "id": "B03.03", - "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "description": "Customer Operational best practice - verify", + "guid": "65e8d9a3-aec2-418e-9436-b0736db55f57", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/remediate-vulnerability-findings-vm", "services": [ - "Subscriptions", - "RBAC", - "ACR", - "Entra" + "Defender", + "VM" ], "severity": "High", - "subcategory": "Identity", - "text": "Enforce a RBAC model that aligns to your cloud operating model. Scope and Assign across Management Groups and Subscriptions.", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "waf": "Security" + "subcategory": "Azure Defender", + "text": "High severity VM vulnerabilities is zero (empty)" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", - "id": "B03.04", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "9603334b-df9c-4c23-918d-b61171265f4b", + "link": "https://techcommunity.microsoft.com/t5/azure-network-security/azure-firewall-manager-is-now-integrated-with-azure-security/ba-p/2228679", "services": [ - "Entra", - "AzurePolicy" + "Firewall", + "Defender" ], - "severity": "Low", - "subcategory": "Identity", - "text": "Enforce Microsoft Entra ID conditional-access policies for any user with rights to Azure environments", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", - "waf": "Security" + "severity": "Medium", + "subcategory": "Firewall Manager", + "text": "Hubs are protected by an Azure Firewall" }, { - "ammp": true, - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", - "id": "B03.05", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "description": "Customer Operational best practice - verify", + "guid": "b47a393a-0803-4272-a479-8b1578a219a4", + "link": "https://learn.microsoft.com/azure/security/fundamentals/network-best-practices", "services": [ - "Entra" + "Firewall", + "Defender", + "VNet" ], - "severity": "High", - "subcategory": "Identity", - "text": "Enforce multi-factor authentication for any user with rights to the Azure environments", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", - "waf": "Security" + "severity": "Medium", + "subcategory": "Firewall Manager", + "text": "Virtual Networks are protected by a Firewall" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", - "id": "B03.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "6ceb5443-5025-4922-9442-92bb628537a5", + "link": "https://azure.microsoft.com/blog/how-azure-security-center-detects-ddos-attack-using-cyber-threat-intelligence/", "services": [ - "RBAC", - "Entra" + "Firewall", + "Defender", + "DDoS" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Enforce centralized and delegated responsibilities to manage resources deployed inside the landing zone, based on role and security requirements", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", - "waf": "Security" + "subcategory": "Firewall Manager", + "text": "DDoS Standard enabled" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "14658d35-58fd-4772-99b8-21112df27ee4", - "id": "B03.07", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "category": "Defender For Cloud", + "checklist": "Azure Security Review Checklist", + "guid": "5119bf8e-8f58-4542-a7d9-cdc166cd072a", + "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started?WT.mc_id=Portal-Microsoft_Azure_Security", "services": [ - "Entra" + "Subscriptions", + "Defender" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Enforce Microsoft Entra ID Privileged Identity Management (PIM) to establish zero standing access and least privilege", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", - "waf": "Security" + "severity": "High", + "subcategory": "Coverage", + "text": "Verify that all subscriptions are covered (see pricing and settings to modify)" }, { - "ammp": true, - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", - "id": "B03.08", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "4df585ec-dce9-4793-a7bc-db3b51eb2eb0", + "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses", "services": [ - "Entra" + "VM", + "VNet" ], "severity": "High", - "subcategory": "Identity", - "text": "Only use the authentication type Work or school account for all account types. Avoid using the Microsoft account", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", - "waf": "Security" + "subcategory": "Public IPs", + "text": "VM's with public IPs should be protected by NSG " }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", - "id": "B03.09", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", - "services": [ - "Entra" - ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Only use groups to assign permissions. Add on-premises groups to the Azure-AD-only group if a group management system is already in place.", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", - "waf": "Security" + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "3dda6e59-d7c8-4a2e-bb11-7d6769af669c", + "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses", + "services": [ + "Firewall", + "VM", + "EventHubs" + ], + "severity": "High", + "subcategory": "Public IPs", + "text": "VMs with public IPs are moved behind Azure Firewall Premium" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "f5664b5e-984a-4859-a773-e7d261623a76", - "id": "B03.10", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "a48e5a85-f222-43ec-b8bb-12308ca5017f", + "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/default-outbound-access", + "services": [ + "VM" + ], + "severity": "High", + "subcategory": "Public IPs", + "text": "VM's that don't need public IPs do not have public IPs (i.e. internal RDP only)" + }, + { + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "158e3ea3-a93c-42de-9e31-65c3a87a04b7", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", "services": [ - "Subscriptions", "RBAC", - "Entra" + "VNet" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Consider using Azure custom roles for the following key roles: Azure platform owner, network management, security operations, subscription owner, application owner", - "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", - "waf": "Security" + "subcategory": "NSG", + "text": "NSG RBAC is used to restrict access to network security team" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", - "id": "B03.11", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "a209939b-da47-4778-b24c-116785c2fa55", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", "services": [ - "Subscriptions", - "Entra" + "VNet" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "If Azure Active Directory Domains Services (AADDS) is in use, deploy AADDS within the primary region because this service can only be projected into one subscription", - "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", - "waf": "Security" + "severity": "High", + "subcategory": "NSG", + "text": "NSG Inbound security rules do not contain a * (wildcard) in Source field" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", - "id": "B03.12", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "b56a9480-08be-47d7-b4c4-76b6d8bdcf59", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", "services": [ - "Entra" + "VNet" ], "severity": "Medium", - "subcategory": "Identity", - "text": "If AADDS in use, evaluate the compatibility of all workloads", - "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", - "waf": "Security" + "subcategory": "NSG", + "text": "NSG outbound security rules are used to control traffic to specific IP addresses for traffic not routed through a Firewall" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", - "id": "B03.13", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "bce65de8-a13f-4988-9946-8d66a786d60f", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", "services": [ - "Entra" + "VNet" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "If AD on Windows server in use, are the resources in Azure using the correct domain controller?", - "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", - "waf": "Security" + "severity": "High", + "subcategory": "NSG", + "text": "NSG do not have Source as a * (wildcard) in place." }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", - "id": "B03.14", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "a6c97be9-955d-404c-9c49-c986cb2d1215", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-nsg-manage-log", "services": [ - "VPN", - "Entra" + "Sentinel", + "VNet" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Consider using Microsoft Entra ID Application Proxy as a VPN or reverse proxy replacement to give remote users secure and authenticated access to internal applications (hosted in the cloud or on-premises).", - "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", - "waf": "Security" + "subcategory": "NSG", + "text": "NSG Diagnostics send NetworkSecurityGroupEvent and NetworkSecurityGroupRuleCounter traffic to Sentinel LAW" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "35037e68-9349-4c15-b371-228514f4cdff", - "id": "B03.15", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "aa124b6e-4df5-485e-adce-9793b7bcdb3b", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "services": [ "RBAC", - "Entra" + "VNet" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Avoid using on-premises synced accounts for Microsoft Entra ID role assignments.", - "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", - "waf": "Security" + "subcategory": "UDR", + "text": "UDR RBAC is used to restrict access to the network security team" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", - "id": "B04.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "51eb2eb0-3dda-46e5-ad7c-8a2edb117d67", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "services": [ - "VNet", - "Entra" + "Firewall", + "VNet" ], - "severity": "Low", - "subcategory": "Landing zones", - "text": "Configure Identity (ADDS) network segmentation through the use of a virtual Network and peer back to the hub. Providing authentication inside application landing zone (legacy).", - "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", - "waf": "Security" + "severity": "High", + "subcategory": "UDR", + "text": "If Zero Trust, then UDR's are used to send all traffic to the Azure Firewall Premium" }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", - "id": "B04.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "69af669c-a48e-45a8-9f22-23ece8bb1230", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "services": [ - "RBAC", - "Storage", - "Entra", - "AKV", - "ACR" + "VNet" ], "severity": "Medium", - "subcategory": "Landing zones", - "text": "Use Azure RBAC to manage data plane access to resources, if possible. E.G - Data Operations across Key Vault, Storage Account and Database Services. ", - "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", - "waf": "Security" + "subcategory": "UDR", + "text": "UDR's that do not send all traffic to AzureFirewallPremium are known and documented." }, { - "category": "Identity and Access Management", - "checklist": "Azure Landing Zone Review", - "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", - "id": "B04.03", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "8ca5017f-158e-43ea-9a93-c2de7e3165c3", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview#default", "services": [ - "Entra" + "VNet" ], - "severity": "Medium", - "subcategory": "Landing zones", - "text": "Use Microsoft Entra ID PIM access reviews to periodically validate resource entitlements.", - "waf": "Security" - }, - { - "ammp": true, - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", - "services": [], "severity": "High", - "subcategory": "Naming and tagging", - "text": "It is recommended to follow Microsoft Best Practice Naming Standards", - "waf": "Security" + "subcategory": "Virtual Networks", + "text": "Customer is familiar with Azure networking defaults / SDN default routing in Azure" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "graph": "resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1)", - "guid": "2df27ee4-12e7-4f98-9f63-04722dd69c5b", - "id": "C02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "description": "Customer operational best practice - verify", + "guid": "a87a04b7-a209-4939-ada4-7778f24c1167", + "link": "https://github.com/MicrosoftDocs/azure-docs/issues/53672", "services": [ - "Subscriptions" + "RBAC", + "VNet" ], "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce reasonably flat management group hierarchy with no more than four levels.", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", - "waf": "Security" + "subcategory": "Virtual Networks", + "text": "VNet RBAC is used to restrict access to the network security team" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "667313b4-f566-44b5-b984-a859c773e7d2", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "85c2fa55-b56a-4948-808b-e7d7e4c476b6", + "link": "https://learn.microsoft.com/azure/virtual-network/policy-reference", "services": [ - "Subscriptions" + "VNet" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce a sandbox management group to allow users to immediately experiment with Azure", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "VNet Security recommendations are remediated and there are no 'At-risk' VNets " }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", - "id": "C02.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "d8bdcf59-bce6-45de-aa13-f98879468d66", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", "services": [ - "Subscriptions", - "RBAC", - "AzurePolicy" + "VNet" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce a platform management group under the root management group to support common platform policy and Azure role assignment", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "VNet Peering connections are understood and expected traffic flows are documented" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", - "id": "C02.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "a786d60f-a6c9-47be-a955-d04c3c49c986", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-service-endpoints-overview", "services": [ - "Subscriptions", - "ExpressRoute", - "DNS", - "VWAN" + "VNet" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce a dedicated connectivity subscription in the Connectivity management group to host an Azure Virtual WAN hub, private Domain Name System (DNS), ExpressRoute circuit, and other networking resources.", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "VNet Service Endpoints are in use, no legacy Public Service Endpoints exist" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "graph": "resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1)", - "guid": "33b6b780-8b9f-4e5c-9104-9d403a923c34", - "id": "C02.05", - "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "1f625659-ee55-480a-9824-9c931213dbd7", + "link": "https://learn.microsoft.com/azure/private-link/private-endpoint-overview", "services": [ - "Subscriptions" + "VNet", + "PrivateLink" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce no subscriptions are placed under the root management group", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "VNet Private Endpoints are in use to allow access from on-premises environments, no legacy public endpoints exist" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", - "id": "C02.06", - "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "fb012f70-943f-4630-9722-ea39d2b1ce63", + "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", "services": [ - "Subscriptions", - "RBAC" + "Monitor", + "VNet" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce that only privileged users can operate management groups in the tenant by enabling Azure RBAC authorization in the management group hierarchy settings", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "VNet Monitoring enabled" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", - "id": "C02.07", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "2055b29b-ade4-4aad-8e8c-39ec94666731", + "link": "https://learn.microsoft.com/azure/virtual-network/kubernetes-network-policies", "services": [ - "Subscriptions" + "AKS", + "VNet", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Enforce management groups under the root-level management group to represent the types of workloads, based on their security, compliance, connectivity, and feature needs.", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "Secure traffic between pods using network policies in Azure Kubernetes Service (AKS)" }, { - "ammp": true, - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "49b82111-2df2-47ee-912e-7f983f630472", - "id": "C02.08", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "3c005674-c1e9-445b-959c-373e7ed71623", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-scenario-udr-gw-nva", "services": [ - "Subscriptions", - "RBAC", - "AzurePolicy", - "Cost" + "NVA", + "VNet" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Enforce a process to make resource owners aware of their roles and responsibilities, access review, budget review, policy compliance and remediate when necessary.", - "waf": "Security" + "subcategory": "Virtual Networks", + "text": "VNet NVA (appliances) customer follows published architecture pattern" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", - "id": "C02.09", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "b375a917-ecbe-448f-ae64-dd7df2e8bbbc", + "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", "services": [ - "Subscriptions" + "Monitor", + "Sentinel", + "VNet" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Ensure that all subscription owners and IT core team are aware of subscription quotas and the impact they have on provision resources for a given subscription.", - "waf": "Security" + "severity": "High", + "subcategory": "Virtual Networks", + "text": "VNet Diagnostic settings are enabled and sending VMProtectionAlerts to the Azure Sentinel LAW" }, { - "ammp": true, - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", - "id": "C02.10", - "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "468155ab-c916-44e9-a09a-ed8c44cf3b2b", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/connectivity-to-azure", "services": [ - "VM", - "Subscriptions", - "AzurePolicy", - "Cost" + "ExpressRoute", + "VPN" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Use Reserved Instances where appropriate to optimize cost and ensure available capacity in target regions. Enforce the use of purchased Reserved Instance VM SKUs via Azure Policy.", - "training": "https://learn.microsoft.com/learn/paths/improve-reliability-modern-operations/", - "waf": "Security" + "subcategory": "Connectivity", + "text": "Use ExpressRoute or VPN to access Azure resources from on-premises environments" }, { - "ammp": true, - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", - "id": "C02.11", - "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "bd8ac2aa-ebca-42a4-9da1-dbf3dd992481", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "services": [ - "Subscriptions", - "Monitor" + "VWAN", + "RBAC" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Enforce a dashboard, workbook, or manual process to monitor used capacity levels", - "training": "https://learn.microsoft.com/learn/paths/monitor-usage-performance-availability-resources-azure-monitor/", - "waf": "Security" + "subcategory": "Virtual WAN", + "text": "VWAN RBAC is used to restrict access to the network security team" }, { - "ammp": true, - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", - "id": "C02.12", - "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "718d1dca-1f62-4565-aee5-580a38249c93", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-global-transit-network-architecture", "services": [ - "Subscriptions", - "Cost" + "VWAN", + "Monitor" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Enforce a process for cost management", - "training": "https://learn.microsoft.com/learn/paths/control-spending-manage-bills/", - "waf": "Security" + "subcategory": "Virtual WAN", + "text": "VWAN Customer is using Secure Hub or external Firewall to route and monitor traffic." }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", - "id": "C02.13", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "1213dbd7-fb01-42f7-8943-f6304722ea39", + "link": "https://learn.microsoft.com/azure/web-application-firewall/overview", "services": [ - "Subscriptions", - "Entra" + "RBAC", + "AppGW" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "If AD on Windows Server, establish a dedicated identity subscription in the Indentity management group, to host Windows Server Active Directory domain controllers", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "waf": "Security" + "severity": "High", + "subcategory": "Application Gateway", + "text": "AppGW RBAC is used to restrict access to the network security team" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", - "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", - "id": "C02.14", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "d2b1ce63-2055-4b29-aade-4aad1e8c39ec", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-front-end-ip", "services": [ - "Subscriptions", - "Cost" + "EventHubs", + "WAF", + "AppGW" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Ensure tags are used for billing and cost management", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "waf": "Security" + "severity": "High", + "subcategory": "Application Gateway", + "text": "AppGW All external facing web services are behind Application Gateways with WAF enabled " }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "250d81ce-8bbe-4f85-9051-6a18a8221e50", - "id": "C03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/regions", - "services": [ - "Cost" - ], + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "94666731-3c00-4567-9c1e-945b459c373e", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-front-end-ip", + "services": [ + "EventHubs", + "WAF", + "AppGW" + ], "severity": "High", - "subcategory": "Regions", - "text": "Select the right Azure region/s for your deployment. Azure is a global-scale cloud platform that provide global coverage through many regions and geographies. Different Azure regions have different characteristics, access and availability models, costs, capacity, and services offered, then it is important to consider all criteria and requirements", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", - "waf": "Reliability" + "subcategory": "Application Gateway", + "text": "AppGW All internal facing web services are behind Application Gateways with WAF enabled " }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "19ca3f89-397d-44b1-b5b6-5e18661372ac", - "id": "C03.02", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-setup-guide/regions#operate-in-multiple-geographic-regions", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "7ed71623-b375-4a91-9ecb-e48fbe64dd7d", + "link": "https://learn.microsoft.com/azure/application-gateway/ssl-overview", "services": [ - "ASR" + "AppGW" ], - "severity": "Medium", - "subcategory": "Regions", - "text": "Consider a multi-region deployment. Depending on customer size, locations, and users presence, operating in multiple regions can be a common choice to deliver services and run applications closer to them. Using a multi-region deployment is also important to provide geo disaster recovery capabilities, to eliminate the dependency from a single region capacity and diminish the risk of a temporary and localized resource capacity constraint", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", - "waf": "Reliability" + "severity": "High", + "subcategory": "Application Gateway", + "text": "AppGW - External facing has TLS/SSL enabled and redirects all traffic to 443 (no port 80 traffic)" }, { - "category": "Resource Organization", - "checklist": "Azure Landing Zone Review", - "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", - "id": "C03.03", - "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", - "services": [], - "severity": "Medium", - "subcategory": "Regions", - "text": "Ensure required services and features are available within the chosen deployment regions", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", - "waf": "Reliability" + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "f2e8bbbc-4681-455a-ac91-64e9909aed8c", + "link": "https://learn.microsoft.com/azure/frontdoor/", + "services": [ + "RBAC", + "FrontDoor" + ], + "severity": "High", + "subcategory": "FrontDoor", + "text": "Front Door RBAC is used to restrict access to the network security team" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "373f482f-3e39-4d39-8aa4-7e566f6082b6", - "id": "D01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-app-delivery", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "44cf3b2b-3818-4baf-a2cf-2149d013a923", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/front-door-security-baseline?toc=/azure/frontdoor/TOC.json", "services": [ + "WAF", "FrontDoor", - "AppGW" + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "App delivery", - "text": "Develop a plan for securing the delivery application content from your Workload spokes using Application Gateway and Azure Front door. You can use the Application Delivery checklist to for recommendations.", - "waf": "Operations" + "severity": "High", + "subcategory": "FrontDoor", + "text": "Front Door is associated with a WAF policy" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", - "id": "D01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", - "services": [], - "severity": "Medium", - "subcategory": "App delivery", - "text": "Perform app delivery within landing zones for both internal-facing (corp) and external-facing apps (online).", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Security" + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "ce574dcc-bd8a-4c2a-aebc-a2a44da1dbf3", + "link": "https://learn.microsoft.com/azure/frontdoor/front-door-custom-domain-https", + "services": [ + "FrontDoor", + "AzurePolicy" + ], + "severity": "High", + "subcategory": "FrontDoor", + "text": "Front Door TLS/SSL policy is configured" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", - "id": "D01.03", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "dd992481-718d-41dc-a1f6-25659ee5580a", + "link": "https://learn.microsoft.com/azure/frontdoor/front-door-url-redirect", "services": [ - "DDoS" + "FrontDoor" ], - "severity": "Medium", - "subcategory": "App delivery", - "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "severity": "High", + "subcategory": "FrontDoor", + "text": "Front Door redirect port 80 to port 443 is configured (listeners)" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", - "id": "D02.01", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "38249c93-1213-4dbd-9fb0-12f70943f630", + "link": "https://learn.microsoft.com/azure/frontdoor/front-door-diagnostics", "services": [ - "ExpressRoute" + "Sentinel", + "FrontDoor" ], - "severity": "Medium", - "subcategory": "Encryption", - "text": "When you're using ExpressRoute Direct, configure MACsec in order to encrypt traffic at the layer-two level between the organization's routers and MSEE. The diagram shows this encryption in flow.", - "waf": "Security" + "severity": "High", + "subcategory": "FrontDoor", + "text": "Front Door diagnostics logs send ApplicationGatewayAccessLog &ApplicationGateway FirewallLog to Sentinel LAW" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", - "id": "D02.02", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", + "category": "Azure Networking", + "checklist": "Azure Security Review Checklist", + "guid": "4722ea39-d2b1-4ce6-9205-5b29bade4aad", + "link": "https://learn.microsoft.com/azure/security/fundamentals/ddos-best-practices", "services": [ - "ExpressRoute", - "VPN" + "DDoS" ], - "severity": "Low", - "subcategory": "Encryption", - "text": "For scenarios where MACsec isn't an option (for example, not using ExpressRoute Direct), use a VPN gateway to establish IPsec tunnels over ExpressRoute private peering. ", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "waf": "Security" + "severity": "High", + "subcategory": "DDOS Protection", + "text": "Enabled for Firewall public IP's (all public IPs)" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", - "id": "D03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "346ad56f-bdb8-44db-8bcd-0a689af63f1e", + "link": "https://learn.microsoft.com/security/compass/identity#a-single-enterprise-directory", "services": [ - "VNet" + "Entra" ], - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "Consider a network design based on the traditional hub-and-spoke network topology for network scenarios that require maximum flexibility.", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "waf": "Security" + "severity": "High", + "subcategory": "Tenant", + "text": "Establish a single enterprise directory for managing identities of full-time employees and enterprise resources." }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", - "id": "D03.02", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "a46108cd-6a76-4749-ae69-b7bf61410010", + "link": "https://learn.microsoft.com/security/compass/identity#synchronized-identity-systems", "services": [ - "NVA", - "VPN", - "VNet", - "Firewall", - "ExpressRoute", - "Entra", - "DNS" + "Entra" ], "severity": "High", - "subcategory": "Hub and spoke", - "text": "Ensure that shared networking services, including ExpressRoute gateways, VPN gateways, and Azure Firewall or partner NVAs in the central-hub virtual network. If necessary, also deploy DNS servers.", - "waf": "Cost" + "subcategory": "Tenant", + "text": "Synchronize your cloud identity with your existing identity systems." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", - "id": "D03.03", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "a1ab96ceb-c149-4ce2-bcad-3bd375ebfc7f", + "link": "https://learn.microsoft.com/security/compass/identity#cloud-provider-identity-source-for-third-parties", "services": [ - "NVA" + "Entra" ], - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance", - "waf": "Reliability" + "severity": "High", + "subcategory": "Tenant", + "text": "Use cloud identity services to host non-employee accounts such as vendors, partners, and customers, rather than rather than including them in your on-premises directory." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", - "id": "D03.04", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "343473ec-ed5c-49e1-98f4-cb09524a23cd", + "link": "https://learn.microsoft.com/security/compass/identity#block-legacy-authentication", "services": [ - "ARS", - "ExpressRoute", - "VPN" + "Entra" ], - "severity": "Low", - "subcategory": "Hub and spoke", - "text": "If you need transit between ExpressRoute and VPN gateways in hub and spoke scenarios, use Azure Route Server.", - "waf": "Security" + "severity": "High", + "subcategory": "Tenant", + "text": "Disable insecure legacy protocols for internet-facing services." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant", - "guid": "91b9d7d5-91e1-4dcb-8f1f-fa7e465646cc", - "id": "D03.05", - "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "70dceb23-50c7-4d8d-bf53-8cc104c7dc44", + "link": "https://learn.microsoft.com/azure/security/fundamentals/identity-management-best-practices#enable-single-sign-on", "services": [ - "VNet", - "ARS" + "Entra" ], - "severity": "Low", - "subcategory": "Hub and spoke", - "text": "If using Route Server, use a /27 prefix for the Route Server subnet.", - "waf": "Security" + "severity": "High", + "subcategory": "Tenant", + "text": "Enable single sign-on" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", - "id": "D03.06", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-faq#can-i-create-a-peering-connection-to-a-vnet-in-a-different-region", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "87791be1-1eb0-48ed-8003-ad9bcf241b99", + "link": "https://learn.microsoft.com/security/compass/identity#no-on-premises-admin-accounts-in-cloud-identity-providers", "services": [ - "VNet", - "ACR" + "Entra" ], - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "For network architectures with multiple hub-and-spoke topologies across Azure regions, use global virtual network peerings between the hub VNets to connect the regions to each other. ", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-virtual-networks/", - "waf": "Performance" + "severity": "High", + "subcategory": "Privileged administration", + "text": "Don’t synchronize accounts with the highest privilege access to on-premises resources as you synchronize your enterprise identity systems with cloud directories." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", - "id": "D03.07", - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "9e6efe9d-f28f-463b-9bff-b5080173e9fe", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices#5-limit-the-number-of-global-administrators-to-less-than-5", "services": [ - "Monitor" + "Entra" ], - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "Use Azure Monitor for Networks to monitor the end-to-end state of the networks on Azure.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", - "waf": "Operations" + "severity": "High", + "subcategory": "Privileged administration", + "text": "Limit the number of Global Administrators to less than 5" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant", - "guid": "0e7c28ec-9366-4572-83b0-f4664b1d944a", - "id": "D03.08", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "e0d968d3-87f6-41fb-a4f9-d852f1673f4c", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices#6-use-groups-for-azure-ad-role-assignments-and-delegate-the-role-assignment", "services": [ - "VNet", - "ExpressRoute", + "RBAC", "Entra" ], - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000)", - "waf": "Reliability" + "severity": "High", + "subcategory": "Privileged administration", + "text": "Use groups for Azure AD role assignments and delegate the role assignment" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant", - "guid": "3d457936-e9b7-41eb-bdff-314b26450b12", - "id": "D03.09", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "00350863-4df6-4050-9cf1-cbaa6d58283e", + "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-admins#managed-accounts-for-admins", "services": [ - "Storage" + "Entra", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "Consider the limit of routes per route table (400).", - "waf": "Reliability" + "severity": "High", + "subcategory": "Privileged administration", + "text": "Ensure all critical impact admins are managed by enterprise directory to follow organizational policy enforcement." }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)", - "guid": "c76cb5a2-abe2-11ed-afa1-0242ac120002", - "id": "D03.10", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "eae64d01-0d3a-4ae1-a89d-cc1c2ad3888f", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices#4-configure-recurring-access-reviews-to-revoke-unneeded-permissions-over-time", "services": [ - "VNet" + "Entra" ], "severity": "High", - "subcategory": "Hub and spoke", - "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings", - "waf": "Reliability" + "subcategory": "Privileged administration", + "text": "Configure recurring access reviews to revoke unneeded permissions over time" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", - "id": "D04.01", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "922ac19f-916d-4697-b8ea-ded26bdd186f", + "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-admins#admin-workstation-security", "services": [ - "ExpressRoute" + "Monitor", + "Entra" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "Ensure that you have investigated the possibility to use ExpressRoute as primary connection to Azure.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Performance" + "subcategory": "Privileged administration", + "text": "Ensure critical impact admins use a workstation with elevated security protections and monitoring" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "description": "You can use AS-path prepending and connection weights to influence traffic from Azure to on-premises, and the full range of BGP attributes in your own routers to influence traffic from on-premises to Azure.", - "guid": "f29812b2-363c-4efe-879b-599de0d5973c", - "id": "D04.02", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "1e8c39ec-9466-4673-83c0-05674c1e945b", + "link": "https://learn.microsoft.com/azure/active-directory/external-identities/compare-with-b2c", "services": [ - "ExpressRoute" + "Entra" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "When you use multiple ExpressRoute circuits, or multiple on-prem locations, make sure to optimize routing with BGP attributes, if certain paths are preferred.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Reliability" + "severity": "High", + "subcategory": "External Identities", + "text": "Identity Providers: Verify external identity providers are known" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant", - "guid": "d4cd21b0-8813-47f5-b6c4-cfd3e504547c", - "id": "D04.03", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "459c373e-7ed7-4162-9b37-5a917ecbe48f", + "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", "services": [ - "ExpressRoute", - "VPN" + "Entra" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Performance" + "severity": "High", + "subcategory": "External Identities", + "text": "External Collaboration Settings: Guest user access set to 'Guest user access is restricted?'" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant", - "guid": "7025b442-f6e9-4af6-b11f-c9574916016f", - "id": "D04.04", - "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "be64dd7d-f2e8-4bbb-a468-155abc9164e9", + "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", "services": [ - "ExpressRoute", - "Cost" + "RBAC", + "Entra" ], "severity": "High", - "subcategory": "Hybrid", - "text": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost.", - "waf": "Cost" + "subcategory": "External Identities", + "text": "External Collaboration Settings: Guest invite settings set to 'Only users assigned to specific admin roles'" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id", - "guid": "f4e7926a-ec35-476e-a412-5dd17136bd62", - "id": "D04.05", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "909aed8c-44cf-43b2-a381-8bafa2cf2149", + "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", "services": [ - "ExpressRoute", - "Cost" + "Entra" ], "severity": "High", - "subcategory": "Hybrid", - "text": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU.", - "waf": "Cost" + "subcategory": "External Identities", + "text": "External Collaboration Settings: Enable guest self-service sign up via flows set to 'Disabled' " }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant", - "guid": "2447ec66-138a-4720-8f1c-e16ed301d6e8", - "id": "D04.06", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "d013a923-ce57-44dc-abd8-ac2aaebca2a4", + "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", "services": [ - "ExpressRoute" + "Entra" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Reliability" + "severity": "High", + "subcategory": "External Identities", + "text": "External Collaboration Settings: Collaboration restrictions set to 'Allow invitations to the specified domains'" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", - "id": "D04.07", - "link": "https://learn.microsoft.com/azure/networking/", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "4da1dbf3-dd99-4248-8718-d1dca1f62565", + "link": "https://learn.microsoft.com/azure/active-directory/governance/deploy-access-reviews", "services": [ - "ExpressRoute" + "Entra" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "For scenarios that require bandwidth higher than 10 Gbps or dedicated 10/100-Gbps ports, use ExpressRoute Direct.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Performance" + "subcategory": "External Identities", + "text": "Access Reviews: Enabled for all groups" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", - "id": "D04.08", - "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "9ee5580a-3824-49c9-9121-3dbd7fb012f7", + "link": "https://learn.microsoft.com/azure/active-directory/manage-apps/configure-user-consent", "services": [ - "ExpressRoute" + "Entra" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "When low latency is required, or throughput from on-premises to Azure must be greater than 10 Gbps, enable FastPath to bypass the ExpressRoute gateway from the data path.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Performance" + "subcategory": "Enterprise Applications", + "text": "Consent & Permissions: Allow user consent for apps from verified publishers" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant", - "guid": "4d873974-8b66-42d6-b15f-512a65498f6d", - "id": "D04.09", - "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", - "services": [ - "VPN" - ], + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "0943f630-4722-4ea3-ad2b-1ce632055b29", + "link": "https://learn.microsoft.com/azure/active-directory/manage-apps/configure-user-consent-groups", + "services": [ + "Entra" + ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available).", - "training": "https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/", - "waf": "Reliability" + "subcategory": "Enterprise Applications", + "text": "Consent & Permissions: Allow group owner consent for selected group owners " }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "718cb437-b060-2589-8856-2e93a5c6633b", - "id": "D04.10", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "bade4aad-1e8c-439e-a946-667313c00567", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy-configure-custom-domain", "services": [ - "ExpressRoute", - "Cost" + "Entra" ], "severity": "High", - "subcategory": "Hybrid", - "text": "If using ExpressRoute Direct, consider using ExpressRoute Local circuits to the local Azure regions to save costs", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Cost" + "subcategory": "Custom Domains", + "text": "Only validated customer domains are registered" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", - "id": "D04.11", - "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "4c1e945b-459c-4373-b7ed-71623b375a91", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/tutorial-enable-sspr", "services": [ - "ExpressRoute" + "Entra", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "When traffic isolation or dedicated bandwidth is required, such as for separating production and nonproduction environments, use different ExpressRoute circuits. It will help you ensure isolated routing domains and alleviate noisy-neighbor risks.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Security" + "severity": "High", + "subcategory": "Password Reset", + "text": "Self-service password reset policy requirement verified compliant." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b30e38c3-f298-412b-8363-cefe179b599d", - "id": "D04.12", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "7ecbe48f-be64-4dd7-bf2e-8bbbc468155a", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/howto-sspr-deployment", "services": [ - "ExpressRoute", - "Monitor" + "Entra" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "Monitor ExpressRoute availability and utilization using built-in Express Route Insights.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Operations" + "subcategory": "Password Reset", + "text": "Set number of days before users are asked to re-confirm authentication information is not set to zero" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", - "id": "D04.13", - "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "bc9164e9-909a-4ed8-a44c-f3b2b3818baf", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/howto-sspr-deployment", "services": [ - "ACR", - "NetworkWatcher", - "Monitor" + "Entra" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Use Connection Monitor for connectivity monitoring across the environment.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Operations" + "severity": "High", + "subcategory": "Password Reset", + "text": "Set number of methods required to reset password are selected" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", - "id": "D04.14", - "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "a2cf2149-d013-4a92-9ce5-74dccbd8ac2a", + "link": "https://learn.microsoft.com/azure/active-directory/roles/delegate-app-roles", "services": [ - "ExpressRoute" + "Entra" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Use ExpressRoute circuits from different peering locations for redundancy.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Reliability" + "severity": "High", + "subcategory": "User Setting", + "text": "Disable 'Users can register applications'" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", - "id": "D04.15", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "aebca2a4-4da1-4dbf-9dd9-92481718d1dc", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/users-default-permissions", "services": [ - "VM" + "Entra" ], "severity": "High", - "subcategory": "Hybrid", - "text": "If you are deploying at least two VMs running AD DS as domain controllers, add them to different Availability Zones. If not available in the region, deploy in an Availability Set.", - "waf": "Reliability" + "subcategory": "User Setting", + "text": "Restrict access to Administrative portal (portal.azure.com) to administrators only" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "558fd772-49b8-4211-82df-27ee412e7f98", - "id": "D05.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "a1f62565-9ee5-4580-a382-49c931213dbd", + "link": "https://learn.microsoft.com/azure/active-directory/enterprise-users/linkedin-integration", "services": [ - "VNet", - "ACR" + "Entra" ], "severity": "High", - "subcategory": "IP plan", - "text": "Ensure no overlapping IP address spaces across Azure regions and on-premises locations are used", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "waf": "Security" + "subcategory": "User Setting", + "text": "Disable 'LinkedIn account connection'" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr", - "guid": "3f630472-2dd6-49c5-a5c2-622f54b69bad", - "id": "D05.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "7fb012f7-0943-4f63-8472-2ea39d2b1ce6", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-monitoring", "services": [ - "VNet" + "Monitor", + "Sentinel", + "Entra" ], - "severity": "Low", - "subcategory": "IP plan", - "text": "Use IP addresses from the address allocation ranges for private internets (RFC 1918).", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "waf": "Security" + "severity": "High", + "subcategory": "Diagnostic Settings", + "text": "Enabled and send to Log Analytics workspace with Sentinel" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant", - "guid": "33aad5e8-c68e-41d7-9667-313b4f5664b5", - "id": "D05.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "21e44a19-a9dd-4399-afd7-b28dc8355562", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-deployment-plan", "services": [ - "VNet" + "Entra" ], "severity": "High", - "subcategory": "IP plan", - "text": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16) ", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "waf": "Performance" + "subcategory": "PIM enabled", + "text": "Privileged Identity Management enabled" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", - "id": "D05.04", - "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "46f4389a-7f42-4c78-b78c-06a63a21a495", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/just-in-time-access-usage?tabs=jit-config-asc%2Cjit-request-asc", "services": [ - "VNet" + "Entra" ], "severity": "High", - "subcategory": "IP plan", - "text": "Avoid using overlapping IP address ranges for production and DR sites.", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", - "waf": "Reliability" + "subcategory": "PIM enabled", + "text": "Implement 'just in time' (JIT) access to further lower the exposure time for privileged accounts (reduce standing access)" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", - "id": "D05.05", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "6e6a8dc4-a20e-427b-9e29-711b1352beee", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/concept-conditional-access-policy-common", "services": [ - "VNet", - "DNS" + "Entra", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "IP plan", - "text": "For environments where name resolution in Azure is all that's required, use Azure Private DNS for resolution with a delegated zone for name resolution (such as 'azure.contoso.com').", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", - "waf": "Operations" + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Configure conditional access policies / Access Controls" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", - "id": "D05.06", - "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "079b588d-efc4-4972-ac3c-d21bf77036e5", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/location-condition", "services": [ - "VNet", - "ACR", - "DNS" + "Entra", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "IP plan", - "text": "For environments where name resolution across Azure and on-premises is required, consider using Azure DNS Private Resolver.", - "training": "https://learn.microsoft.com/training/modules/intro-to-azure-dns-private-resolver/", - "waf": "Security" + "subcategory": "Conditional Access Policies", + "text": "Conditions: Restricted Locations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", - "id": "D05.07", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "e6b4bed3-d5f3-4547-a134-7dc56028a71f", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/tutorial-enable-azure-mfa", "services": [ - "VNet", - "DNS" + "Entra", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "IP plan", - "text": "Special workloads that require and deploy their own DNS (such as Red Hat OpenShift) should use their preferred DNS solution.", - "waf": "Operations" + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: MFA enabled for all users" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "614658d3-558f-4d77-849b-821112df27ee", - "id": "D05.08", - "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "fe1bd15d-d2f0-4d5e-972d-41e3611cc57b", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-admin-mfa", "services": [ - "VM", - "VNet", - "DNS" + "Entra", + "AzurePolicy" ], - "severity": "High", - "subcategory": "IP plan", - "text": "Enable auto-registration for Azure DNS to automatically manage the lifecycle of the DNS records for the virtual machines deployed within a virtual network.", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Require MFA for Administrators" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", - "id": "D06.01", - "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "4a4b1410-d439-4589-ac22-89b3d6b57cfc", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-azure-management", "services": [ - "Bastion" + "Entra", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Consider using Azure Bastion to securely connect to your network.", - "waf": "Security" + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Require MFA for Azure Management " }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant", - "guid": "6eab9eb6-762b-485e-8ea8-15aa5dba0bd0", - "id": "D06.02", - "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "645461e1-a3e3-4453-a3c8-639637a552d6", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-block-legacy", "services": [ - "VNet", - "Bastion" + "Entra", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Bastion in a subnet /26 or larger.", - "waf": "Security" + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Block Legacy Protocols" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", - "id": "D06.03", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "7ae9eab4-0fd3-4290-998b-c178bdc5a06c", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/require-managed-devices", "services": [ - "Firewall" + "Entra", + "AzurePolicy" ], "severity": "High", - "subcategory": "Internet", - "text": "Use Azure Firewall to govern Azure outbound traffic to the internet, non-HTTP/S inbound connections, and East/West traffic filtering (if the organization requires it)", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Require devices to be marked as compliant" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", - "id": "D06.04", - "link": "https://learn.microsoft.com/azure/firewall/", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "description": "Customer documented policy", + "guid": "a7144351-e19d-4d34-929e-b7228137a151", + "link": "https://devblogs.microsoft.com/premier-developer/azure-active-directory-automating-guest-user-management/", "services": [ - "Firewall", - "RBAC", - "ACR", + "Entra", "AzurePolicy" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Create a global Azure Firewall policy to govern security posture across the global network environment and assign it to all Azure Firewall instances. Allow for granular policies to meet requirements of specific regions by delegating incremental firewall policies to local security teams via Azure role-based access control.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "subcategory": "Guest users", + "text": "Is there a policy to track guest user accounts (i.e. usage/delete/disable)?" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", - "id": "D06.05", - "link": "https://learn.microsoft.com/azure/firewall/", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "c5bb4e4f-1814-4287-b5ca-8c26c9b32ab5", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/identity-secure-score", "services": [ - "Firewall" + "Entra" ], - "severity": "Low", - "subcategory": "Internet", - "text": "Configure supported partner SaaS security providers within Firewall Manager if the organization wants to use such solutions to help protect outbound connections.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "severity": "High", + "subcategory": "Identity Secure Score", + "text": "Implement Identity Secure Score based on best practices in your industry" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", - "id": "D06.06", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", + "category": "Identity", + "checklist": "Azure Security Review Checklist", + "guid": "bcfc6998-a135-4e33-9897-e31c67d68cb6", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "services": [ - "FrontDoor", - "ACR", - "AzurePolicy", - "WAF" + "Entra", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Front Door and WAF policies to provide global protection across Azure regions for inbound HTTP/S connections to a landing zone.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Security" + "subcategory": "Break Glass Accounts", + "text": "At least two break glass accounts have been created and policy around their use exists" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", - "id": "D06.07", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "0ac252b9-99a6-48af-a7c9-a8f821b8eb8c", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "FrontDoor", - "AzurePolicy", - "AppGW", - "WAF" + "VM", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Internet", - "text": "When using Azure Front Door and Azure Application Gateway to help protect HTTP/S apps, use WAF policies in Azure Front Door. Lock down Azure Application Gateway to receive traffic only from Azure Front Door.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Security" + "severity": "High", + "subcategory": "Access Control", + "text": "Control VM Access leveraging Azure Policy" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", - "id": "D06.08", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "0aa77e26-e4d5-4aea-a8dc-4e2436bc336d", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/templates/syntax", "services": [ - "VNet", - "WAF" + "VM" ], - "severity": "High", - "subcategory": "Internet", - "text": "Deploy WAFs and other reverse proxies are required for inbound HTTP/S connections, deploy them within a landing-zone virtual network and together with the apps that they're protecting and exposing to the internet.", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "waf": "Security" + "severity": "Medium", + "subcategory": "Access Control", + "text": "Reduce variability in your setup and deployment of VMs by leveraging templates" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", - "id": "D06.09", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "b5945bda-4333-44fd-b91c-234182b65275", + "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/security-best-practices/implementing-least-privilege-administrative-models", "services": [ - "VNet", - "DDoS" + "VM" ], - "severity": "High", - "subcategory": "Internet", - "text": "Use Azure DDoS Network or IP Protection plans to help protect Public IP Addresses endpoints within the virtual networks.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "severity": "Medium", + "subcategory": "Access Control", + "text": "Secure privileged access to deploy VMS by reducing who has access to Resources through Governance" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", - "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", - "id": "D06.10", - "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "269440b4-be3d-43e0-a432-76d4bdc015bc", + "link": "https://learn.microsoft.com/azure/architecture/checklist/resiliency-per-service", "services": [ - "Firewall", - "DNS" + "VM" ], - "severity": "High", - "subcategory": "Internet", - "text": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules.", - "waf": "Security" + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Use multiple VMs for your workloads for better availability " }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", - "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", - "id": "D06.11", - "link": "https://learn.microsoft.com/azure/firewall/premium-features", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "f219e4a1-eb58-4879-935d-227886d30b66", + "link": "https://learn.microsoft.com/azure/backup/backup-azure-vms-first-look-arm", "services": [ - "Firewall" + "VM", + "ASR" ], - "severity": "High", - "subcategory": "Internet", - "text": "Use Azure Firewall Premium for additional security and protection.", - "waf": "Security" - }, + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Deploy and test a disaster recovery solution " + }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", - "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", - "id": "D06.12", - "link": "https://learn.microsoft.com/azure/firewall/premium-features", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "c57be595-1900-4838-95c5-86cb291ec16a", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability-set-overview", "services": [ - "Firewall" + "VM" ], - "severity": "High", - "subcategory": "Internet", - "text": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection.", - "waf": "Security" + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Availability sets" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", - "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", - "id": "D06.13", - "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "1d076ef9-f141-4acd-ae57-9377bcdb3751", + "link": "https://learn.microsoft.com/azure/availability-zones/az-overview?context=/azure/virtual-machines/context/context", "services": [ - "Firewall" + "VM" ], - "severity": "High", - "subcategory": "Internet", - "text": "Configure Azure Firewall IDPS mode to Deny for additional protection.", - "waf": "Security" + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Availability Zones" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant", - "guid": "a3784907-9836-4271-aafc-93535f8ec08b", - "id": "D06.14", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "ab2ac1fa-d66e-415d-9d5a-2adb2c3e2326", + "link": "https://learn.microsoft.com/azure/architecture/resiliency/recovery-loss-azure-region", "services": [ - "NVA", - "Storage", - "VNet", - "Firewall", - "VWAN" + "VM" ], - "severity": "High", - "subcategory": "Internet", - "text": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance", - "waf": "Security" - }, - { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b034c01e-110b-463a-b36e-e3346e57f225", - "id": "D06.15", - "link": "https://learn.microsoft.com/en-us/azure/virtual-network/ip-services/default-outbound-access", - "services": [], - "severity": "High", - "subcategory": "Internet", - "text": "Assess and review network outbound traffic configuration and strategy before the upcoming breaking change. On September 30, 2025, default outbound access for new deployments will be retired and only explicit access configurations will be allowed", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Regional fault tolerance " }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", - "id": "D07.01", - "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "af225ca4-4e16-496f-bdde-ace4cb1deb4c", + "link": "https://learn.microsoft.com/azure/security/fundamentals/antimalware", "services": [ - "VNet" + "VM" ], "severity": "High", - "subcategory": "PaaS", - "text": "Ensure that control-plane communication for Azure PaaS services injected into a virtual network is not broken, for example with a 0.0.0.0/0 route or an NSG rule that blocks control plane traffic.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", - "waf": "Security" + "subcategory": "Protect against malware", + "text": "Install antimalware solutions" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", - "id": "D07.02", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "650c3fc1-4eeb-4b36-a382-9e3eec218368", + "link": "https://learn.microsoft.com/azure/security-center/security-center-partner-integration", "services": [ - "PrivateLink" + "Defender", + "VM" ], - "severity": "Medium", - "subcategory": "PaaS", - "text": "Use Private Link, where available, for shared Azure PaaS services.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "waf": "Security" + "severity": "High", + "subcategory": "Protect against malware", + "text": "Integrate antimalware solution with Security Center" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", - "id": "D07.03", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "7a0177a2-b594-45bd-a433-34fdf91c2341", + "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "services": [ - "PrivateLink", - "ExpressRoute" + "VM" ], - "severity": "Medium", - "subcategory": "PaaS", - "text": "Access Azure PaaS services from on-premises via private endpoints and ExpressRoute private peering. This method avoids transiting over the public internet.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "waf": "Security" + "severity": "High", + "subcategory": "Manage VM Updates", + "text": "Keep VMs up to date using Update Management with Azure Automation" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc", - "guid": "4704489a-8042-4d88-b79d-17b73b22a5a6", - "id": "D07.04", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "c6fa96b9-6ad8-4840-af37-2734c876ba28", + "link": "https://learn.microsoft.com/azure/virtual-machines/automatic-vm-guest-patching", "services": [ - "VNet" + "VM" ], "severity": "Medium", - "subcategory": "PaaS", - "text": "Don't enable virtual network service endpoints by default on all subnets.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", - "waf": "Security" + "subcategory": "Manage VM Updates", + "text": "Ensure Windows images for deployment have the most recent level of updates " }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", - "id": "D07.05", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "02145901-465d-438e-9309-ccbd979266bc", + "link": "https://learn.microsoft.com/azure/security-center/asset-inventory", "services": [ - "PrivateLink", - "Firewall", - "NVA", - "DNS" + "Defender", + "VM" ], - "severity": "Medium", - "subcategory": "PaaS", - "text": "Filter egress traffic to Azure PaaS services using FQDNs instead of IP addresses in Azure Firewall or an NVA to prevent data exfiltration. If using Private Link you can block all FQDNs, otherwise allow only the required PaaS services.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", - "waf": "Security" + "severity": "High", + "subcategory": "Manage VM Updates", + "text": "Rapidly apply security updates to VMs using Microsoft Defender for Cloud" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant", - "guid": "22d6419e-b627-4d95-9e7d-019fa759387f", - "id": "D08.01", - "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "ca274faa-19bf-439d-a5d4-4c7c8919ca1f", + "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", "services": [ - "VNet", - "Firewall" + "VM" ], "severity": "High", - "subcategory": "Segmentation", - "text": "Use a /26 prefix for your Azure Firewall subnets.", - "waf": "Security" + "subcategory": "Encrypt your VHDs", + "text": "Enable encryption on your VMs" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant", - "guid": "f2aad7e3-bb03-4adc-8606-4123d342a917", - "id": "D08.02", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "6d5315ae-524b-4a34-b458-5e12139bd7bb", + "link": "https://learn.microsoft.com/azure/virtual-machines/windows/disk-encryption-key-vault#set-up-a-key-encryption-key-kek", "services": [ - "VNet", - "ExpressRoute", - "VPN" + "VM" ], "severity": "High", - "subcategory": "Segmentation", - "text": "Use at least a /27 prefix for your Gateway subnets", - "waf": "Security" + "subcategory": "Encrypt your VHDs", + "text": "Add Key Encryption Key (KEK) for added layer of security for encryption " }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)", - "guid": "11deb39d-8299-4e47-bbe0-0fb5a36318a8", - "id": "D08.03", - "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "012f7b95-e06e-4154-b2aa-3592828e6e20", + "link": "https://learn.microsoft.com/azure/virtual-machines/windows/snapshot-copy-managed-disk", "services": [ - "VNet" + "VM", + "LoadBalancer" ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity.", - "waf": "Security" + "subcategory": "Encrypt your VHDs", + "text": "Take a snapshot of disks before encryption for rollback purposes" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", - "id": "D08.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "5173676a-e466-491e-a835-ad942223e138", + "link": "https://learn.microsoft.com/azure/role-based-access-control/built-in-roles", "services": [ - "VNet" + "VM", + "Entra" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "Delegate subnet creation to the landing zone owner. ", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "waf": "Security" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", - "id": "D08.05", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "services": [ - "VNet", - "ACR" - ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "Use NSGs to help protect traffic across subnets, as well as east/west traffic across the platform (traffic between landing zones).", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "waf": "Security" + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Ensure only the central networking group has permissions to networking resources " }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)", - "guid": "9c2299c4-d7b5-47d0-a655-562f2b3e4563", - "id": "D08.06", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "10523081-a941-4741-9833-ff7ad7c6d373", + "link": "https://learn.microsoft.com/azure/security-center/security-center-partner-integration", "services": [ "VM", - "VNet" - ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "waf": "Security" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", - "id": "D08.07", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", - "services": [ - "VNet", - "NVA", "Entra" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "Use NSGs and application security groups to micro-segment traffic within the landing zone and avoid using a central NVA to filter traffic flows.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "waf": "Security" + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Identity and remediate exposed VMs that allow access from 'ANY' source IP address" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "dfe237de-143b-416c-91d7-aa9b64704489", - "id": "D08.08", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "75a91be1-f388-4f03-a4d2-cd463cbbbc86", + "link": "https://learn.microsoft.com/azure/security-center/security-center-just-in-time", "services": [ - "VNet", - "NetworkWatcher" + "VM" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "Enable NSG flow logs and feed them into Traffic Analytics to gain insights into internal and external traffic flows.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", - "waf": "Security" + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Restrict management ports (RDP, SSH) using Just-in-Time Access" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", - "id": "D09.01", - "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "8295abc9-1a4e-4da0-bae2-cc84c47b6b78", + "link": "http://learn.microsoft.com/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", "services": [ - "VWAN" + "VM" ], - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Consider Virtual WAN for simplified Azure networking management, and make sure your scenario is explicitly described in the list of Virtual WAN routing designs", - "training": "https://learn.microsoft.com/learn/modules/introduction-azure-virtual-wan/", - "waf": "Operations" + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Remove internet access and implement jump servers for RDP" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", - "id": "D09.02", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "1cbafe6c-4658-49d4-98a9-27c3974d1102", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-forced-tunneling", "services": [ - "ACR", - "VWAN" + "VPN", + "VM" ], - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Use a Virtual WAN hub per Azure region to connect multiple landing zones together across Azure regions via a common global Azure Virtual WAN.", - "waf": "Performance" + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Remove direct logging into servers using RDP/SSH from internet and implement VPN or express route" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", - "id": "D09.03", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "category": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "dad6aae1-1e6b-484e-b5df-47d2d92881b1", + "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", "services": [ - "ACR", - "VWAN" + "VM", + "Bastion" ], - "severity": "Low", - "subcategory": "Virtual WAN", - "text": "Follow the principle 'traffic in Azure stays in Azure' so that communication across resources in Azure occurs via the Microsoft backbone network", - "waf": "Performance" + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Leverage Azure Bastion as your RDP/SSH broker for added security and reduction in footprint" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", - "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", - "id": "D09.04", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "cd5d1e54-a297-459e-9968-0e78289c9356", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "services": [ - "Firewall", - "VWAN" + "Monitor", + "Sentinel" ], - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "severity": "High", + "subcategory": "Architecture ", + "text": "All tenants contain have Sentinel enabled on at least one Log Analytics workspace" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", - "id": "D09.05", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "57d02bff-4564-4b0d-a34a-359836ee79d6", + "link": "https://learn.microsoft.com/azure/sentinel/best-practices-workspace-architecture", "services": [ - "VWAN" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Ensure that the network architecture is within the Azure Virtual WAN limits.", - "waf": "Reliability" + "severity": "High", + "subcategory": "Architecture ", + "text": "Customer understands Sentinel architecture" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", - "id": "D09.06", - "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "e8f5c586-c7d9-4cdc-86ac-c075ef9b141a", + "link": "https://learn.microsoft.com/azure/sentinel/multiple-workspace-view", "services": [ - "VWAN", - "Monitor" + "Monitor", + "Sentinel", + "ACR" ], "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Use Azure Monitor Insights for Virtual WAN to monitor the end-to-end topology of the Virtual WAN, status, and key metrics.", - "waf": "Operations" + "subcategory": "Architecture ", + "text": "Customer knows how to monitor Incidents across multiple Sentinel instances" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", - "id": "D09.07", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "8989579e-76b8-497e-910a-7da7be9966e1", + "link": "https://learn.microsoft.com/azure/sentinel/manage-soc-with-incident-metrics", "services": [ - "VWAN" + "Sentinel" ], "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Make sure that your IaC deployments does not disable branch-to-branch traffic in Virtual WAN, unless these flows should be explicitly blocked.", - "waf": "Reliability" + "subcategory": "Overview", + "text": "No Incidents open more than 24 hours" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", - "id": "D09.08", - "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "5d3c4ada-97cb-43d1-925a-b225c6f4e068", + "link": "https://learn.microsoft.com/azure/sentinel/whats-new", "services": [ - "ExpressRoute", - "VPN", - "VWAN" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Use AS-Path as hub routing preference, since it is more flexible than ExpressRoute or VPN.", - "waf": "Reliability" + "severity": "Low", + "subcategory": "News & Guides", + "text": "Customer have been shown the News & Guides tab" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", - "id": "D09.09", - "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "5edddea8-a4b7-4cde-a4c6-1fc3fc14eea6", + "link": "https://learn.microsoft.com/azure/sentinel/enable-entity-behavior-analytics", "services": [ - "VWAN" + "Sentinel" ], "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Make sure that your IaC deployments are configuring label-based propagation in Virtual WAN, otherwise connectivity between virtual hubs will be impaired.", - "waf": "Reliability" + "subcategory": "UEBA ", + "text": "UEBA Configured (Sentinel/Settings/Settings/Configure UEBA)" }, { - "ammp": true, - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "9c75dfef-573c-461c-a698-68598595581a", - "id": "D09.10", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "e69d8d9a-3eec-4218-b687-ab077adb49e5", + "link": "https://learn.microsoft.com/azure/sentinel/connect-azure-active-directory", "services": [ - "VWAN" + "Sentinel", + "Entra" ], "severity": "High", - "subcategory": "Virtual WAN", - "text": "Assign enough IP space to virtual hubs, ideally a /23 prefix.", - "waf": "Reliability" + "subcategory": "Data Connectors", + "text": "Azure Active Directory in configured and 'Last Log Received' shows today" }, { - "ammp": true, - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", - "id": "E01.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "b9603334-fdf8-4cc2-9318-db61171269f4", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#azure-active-directory-identity-protection", "services": [ - "AzurePolicy" + "Sentinel", + "Entra" ], "severity": "High", - "subcategory": "Governance", - "text": "Leverage Azure Policy strategically, define controls for your environment, using Policy Initiatives to group related policies.", - "waf": "Security" + "subcategory": "Data Connectors", + "text": "Azure Active Directory Identity Protection is configured and 'Last Log Received' shows today" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", - "id": "E01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "0b4aa3d3-e070-4327-9d4b-98b15b8a219a", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#azure-activity", "services": [ - "AzurePolicy" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Identify required Azure tags and use the 'append' policy mode to enforce usage via Azure Policy.", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Azure Activity is configured is configured and 'Last Log Received' shows today" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", - "id": "E01.03", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "8e13f9cc-bd46-4826-9abc-a264f9a19bfe", + "link": "https://learn.microsoft.com/azure/sentinel/connect-defender-for-cloud", "services": [ - "RBAC", - "AzurePolicy" + "Defender", + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments.", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Microsoft Defender for Cloud is configured and 'Last Log Received' shows today" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "223ace8c-b123-408c-a501-7f154e3ab369", - "id": "E01.04", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "9d55d04c-3c49-419c-a1b2-d1215ae114b9", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#azure-firewall", "services": [ - "Subscriptions", - "AzurePolicy" + "Firewall", + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Establish Azure Policy definitions at the intermediate root management group so that they can be assigned at inherited scopes", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Azure Firewall is configured and 'Last Log Received' shows today" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "3829e7e3-1618-4368-9a04-77a209945bda", - "id": "E01.05", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "34df585e-cccd-49bd-9ba0-cdb3b54eb2eb", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#windows-firewall", "services": [ - "AzurePolicy" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required.", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Windows Firewall is configured and 'Last Log Received' shows today" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "43334f24-9116-4341-a2ba-527526944008", - "id": "E01.06", - "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "03ddaa25-9271-48d2-bdb1-0725769ef669", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#windows-security-events-via-ama", "services": [ - "Subscriptions", - "AzurePolicy" + "Sentinel" ], - "severity": "Low", - "subcategory": "Governance", - "text": "Use Azure Policy to control which services users can provision at the subscription/management group level", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Security Events is configured with AMA and 'Last Log Received' shows today" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", - "id": "E01.07", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "1a4834ac-9322-423e-ae80-b123081a5417", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", "services": [ - "AzurePolicy" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Use built-in policies where possible to minimize operational overhead.", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Security Events - verify Azure computers are connected and sending data to the workspace" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "description": "Assigning the Resource Policy Contributor role to specific scopes allows you to delegate policy management to relevant teams. For instance, a central IT team may oversee management group-level policies, while application teams handle policies for their subscriptions, enabling distributed governance with adherence to organizational standards.", - "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", - "id": "E01.08", - "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "859c773e-7e26-4162-9b77-5a917e1f348e", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", "services": [ - "Subscriptions", - "RBAC", - "Entra", - "AzurePolicy" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Assign the built-in Resource Policy Contributor role at a particular scope to enable application-level governance.", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Security Events - verify non-Azure computers are connected and sending data to the workspace" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "19048384-5c98-46cb-8913-156a12476e49", - "id": "E01.09", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "f354c27d-42e8-4bba-a868-155abb9163e9", + "link": "https://learn.microsoft.com/azure/sentinel/connect-aws?tabs=s3", "services": [ - "Subscriptions", - "AzurePolicy" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Limit the number of Azure Policy assignments made at the root management group scope to avoid managing through exclusions at inherited scopes.", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Connector for AWS" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", - "id": "E01.10", - "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "909ae28c-84c3-43b6-a780-8bafe6c42149", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", "services": [ - "AzurePolicy" + "Sentinel" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "If any data sovereignty requirements exist, Azure Policies can be deployed to enforce them", - "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", - "waf": "Security" + "severity": "High", + "subcategory": "Data Connectors", + "text": "Connector for GCP" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", - "id": "E02.01", - "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "d413a923-c357-44d1-8028-ac6aae01e6a8", + "link": "https://learn.microsoft.com/azure/sentinel/detect-threats-built-in", "services": [ - "VM", - "TrafficManager", - "Cost" + "Sentinel" ], - "severity": "Low", - "subcategory": "Optimize your cloud investment", - "text": "Consider using automation tags to start/stop VM's in your environment to save on cost.", - "waf": "Security" + "severity": "High", + "subcategory": "Analytics Rules", + "text": "Customer has enabled Analytics rules and configured Incidents " }, { - "category": "Management ", - "checklist": "Azure Landing Zone Review", - "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", - "id": "E02.01", - "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "4de5df43-d299-4248-8718-d5d1e5f62565", + "link": "https://azure.microsoft.com/updates/controlling-data-volume-and-retention-in-log-analytics-2/", "services": [ - "VM" + "Sentinel" ], "severity": "Medium", - "subcategory": "Scalability", - "text": "Leverage Azure Virtual Machine Scale sets to scale in and out based on the load.", - "waf": "Reliability" + "subcategory": "Settings", + "text": "Customer does not have a daily cap enabled" }, { - "category": "Governance", - "checklist": "Azure Landing Zone Review", - "guid": "29fd366b-a180-452b-9bd7-954b7700c667", - "id": "E02.02", - "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "9e3558fd-7724-49c9-9111-2d027fe412f7", + "link": "https://learn.microsoft.com/azure/firewall/premium-features", "services": [ - "Monitor", - "TrafficManager", - "Cost" + "Firewall" ], - "severity": "Medium", - "subcategory": "Optimize your cloud investment", - "text": "Configure 'Actual' and 'Forecasted' Budget Alerts.", - "waf": "Cost" + "severity": "High", + "subcategory": "Configuration", + "text": "Azure Firewall Premium deployed" }, { - "ammp": true, - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", - "id": "F01.01", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "4dc74a74-8b66-433a-b2a0-916a764980ad", + "link": "https://learn.microsoft.com/azure/firewall/tutorial-firewall-deploy-portal#create-a-default-route", "services": [ - "FrontDoor", - "AppGW", - "WAF" + "Firewall" ], "severity": "High", - "subcategory": "App delivery", - "text": "Add diagnostic settings to save WAF logs from application delivery services like Azure Front Door and Azure Application Gateway. Regularly review the logs to check for attacks and for false positive detections.", - "waf": "Operations" + "subcategory": "Configuration", + "text": "Quad zero/force tunning enabled through Azure Firewall" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "7f408960-c626-44cb-a018-347c8d790cdf", - "id": "F01.02", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "0e278ee2-93c1-4bc3-92ba-aab7571849ab", + "link": "https://techcommunity.microsoft.com/t5/azure-network-security/role-based-access-control-for-azure-firewall/ba-p/2245598", "services": [ - "FrontDoor", - "Sentinel", - "AppGW", - "WAF" + "Firewall", + "RBAC" ], "severity": "Medium", - "subcategory": "App delivery", - "text": "Send WAF logs from your application delivery services like Azure Front Door and Azure Application Gateway to Microsoft Sentinel. Detect attacks and integrate WAF telemetry into your overall Azure environment.", - "waf": "Operations" + "subcategory": "Access Control", + "text": "RBAC set to enable only authorized users" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", - "id": "F02.01", - "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", - "services": [], + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "8093dc9f-c9d1-4bb7-9b36-a5a67fbb9ed5", + "link": "https://learn.microsoft.com/azure/firewall/firewall-diagnostics", + "services": [ + "Firewall", + "Monitor" + ], "severity": "Medium", - "subcategory": "Data Protection", - "text": "Consider cross-region replication in Azure for BCDR with paired regions", - "waf": "Reliability" + "subcategory": "Diagnostic Settings", + "text": "Diagnostics enabled and sending metrics to a Log Analytics workspace " }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", - "id": "F02.02", - "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "b35478c3-4798-416b-8863-cffe1cac599e", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "services": [ - "Backup" + "Firewall", + "VNet" ], - "severity": "Medium", - "subcategory": "Data Protection", - "text": "When using Azure Backup, consider the different backup types (GRS, ZRS & LRS) as the default setting is GRS", - "waf": "Reliability" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Hubs and virtual networks are protected or connected through Firewall Premium" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", - "id": "F03.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "f0d5a73d-d4de-436c-8c81-770afbc4c0e4", + "link": "https://techcommunity.microsoft.com/t5/azure-network-security/role-based-access-control-for-azure-firewall/ba-p/2245598", "services": [ + "Firewall", "RBAC", - "Entra", - "AzurePolicy", - "Monitor" + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use a single monitor logs workspace to manage platforms centrally except where Azure role-based access control (Azure RBAC), data sovereignty requirements, or data retention policies mandate separate workspaces.", - "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Access controls are configured (RBAC)" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", - "id": "F03.02", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "5c3a87af-4a79-41f8-a39b-da47768e14c1", + "link": "https://learn.microsoft.com/azure/firewall-manager/policy-overview", "services": [ - "Monitor" + "Firewall", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Is the landing zone documented?", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Parent policy is configured " }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", - "id": "F03.03", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "15675c1e-a55b-446a-a48f-f8ae7d7e4b47", + "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "ARS", - "Monitor" + "Firewall", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor Logs when log retention requirements exceed two years. You can currently keep data in archived state for up to 7 years.", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Rule collections are defined" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", - "id": "F03.04", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/govern/policy-compliance/regulatory-compliance", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "5b6c8bcb-f59b-4ce6-9de8-a03f97879468", + "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "AzurePolicy", - "Monitor" + "Firewall", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Policy for access control and compliance reporting. Azure Policy provides the ability to enforce organization-wide settings to ensure consistent policy adherence and fast violation detection. ", - "training": "https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effects", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: DNAT policies are defined" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", - "id": "F03.05", - "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "d66a786d-60e9-46c9-9ad8-855d04c2b39c", + "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "VM", - "AzurePolicy", - "Monitor" + "Firewall", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Monitor in-guest virtual machine (VM) configuration drift using Azure Policy. Enabling guest configuration audit capabilities through policy helps application team workloads to immediately consume feature capabilities with little effort.", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Network rules are defined" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", - "id": "F03.06", - "link": "https://learn.microsoft.com/azure/automation/update-management/overview", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "986bb2c1-2149-4a11-9b5e-3df574ecccd9", + "link": "https://learn.microsoft.com/azure/firewall/features", "services": [ - "VM", - "Monitor" + "Firewall", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Update Management in Azure Automation as a long-term patching mechanism for both Windows and Linux VMs. ", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Application rules are defined" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "90483845-c986-4cb2-a131-56a12476e49f", - "id": "F03.07", - "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "793a6bcd-a3b5-40eb-8eb0-3dd95d58d7c8", + "link": "https://learn.microsoft.com/azure/firewall/dns-details", "services": [ - "NetworkWatcher", - "Monitor" + "Firewall", + "DNS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Network Watcher to proactively monitor traffic flows", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", - "waf": "Operations" + "subcategory": "Firewall Manager", + "text": "DNS: Feature understood and applied or not applied" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", - "id": "F03.08", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "d622f54b-29ba-4de3-aad1-e8c28ec93666", + "link": "https://learn.microsoft.com/azure/firewall-manager/threat-intelligence-settings", "services": [ - "Monitor" + "Firewall" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use resource locks to prevent accidental deletion of critical shared services.", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Threat Intelligence: Set to Alert & Deny" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", - "id": "F03.09", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "7313b005-674b-41e9-94a4-59c373e7ed61", + "link": "https://learn.microsoft.com/azure/firewall-manager/threat-intelligence-settings#allowlist-addresses", "services": [ - "RBAC", - "AzurePolicy", - "Monitor" + "Firewall" ], - "severity": "Low", - "subcategory": "Monitoring", - "text": "Use deny policies to supplement Azure role assignments. The combination of deny policies and Azure role assignments ensures the appropriate guardrails are in place to enforce who can deploy and configure resources and what resources they can deploy and configure.", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Threat Intelligence: Allowed list (justify if they are being used - ie performance)" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", - "id": "F03.10", - "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "623b365a-917e-4cbe-98eb-d54cd7df2e8b", + "link": "https://learn.microsoft.com/azure/firewall/premium-certificates", "services": [ - "Monitor" + "Firewall" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Include service and resource health events as part of the overall platform monitoring solution. Tracking service and resource health from the platform perspective is an important component of resource management in Azure.", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "TLS enabled" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", - "id": "F03.11", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "bac35715-59ab-4915-9e99-08aed8c44ce3", + "link": "https://learn.microsoft.com/azure/firewall/rule-processing", "services": [ - "Monitor" + "Firewall" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Include alerts and action groups as part of the Azure Service Health platform to ensure that alerts or issues can be actioned", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "IDPS enabled" }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", - "id": "F03.12", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "b2b3808b-9fa1-4cf1-849d-003a923ce474", + "link": "https://learn.microsoft.com/azure/firewall/snat-private-range", "services": [ - "Monitor" + "Firewall" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Don't send raw log entries back to on-premises monitoring systems. Instead, adopt a principle that data born in Azure stays in Azure. If on-premises SIEM integration is required, then send critical alerts instead of logs.", - "waf": "Operations" + "severity": "High", + "subcategory": "Firewall Manager", + "text": "SNAT: Configured " }, { - "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "9945bda4-3334-4f24-a116-34182ba52752", - "id": "F03.13", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "dbcbd8ac-2aae-4bca-8a43-da1dae2cc992", + "link": "https://learn.microsoft.com/azure/security/fundamentals/ddos-best-practices", "services": [ - "RBAC", - "Entra", - "Monitor" + "Firewall", + "DDoS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use a centralized Azure Monitor Log Analytics workspace to collect logs and metrics from IaaS and PaaS application resources and control log access with Azure RBAC.", - "waf": "Operations" + "subcategory": "DDOS Protection", + "text": "Enabled for Firewall public IP's" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", - "id": "F03.14", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", + "checklist": "Azure API Management Review", + "guid": "06862505-2d9a-4874-9491-2837b00a3475", + "link": "https://learn.microsoft.com/azure/api-management/backends", "services": [ - "Monitor" + "APIM" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor Logs for insights and reporting.", - "waf": "Operations" + "subcategory": "Best practices", + "text": "Use Backends feature to eliminate redundant API backend configurations" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", - "id": "F03.15", - "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", + "checklist": "Azure API Management Review", + "guid": "03b125d5-b69b-4739-b7fd-84b86da4933e", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-properties?tabs=azure-portal", "services": [ - "Storage", - "Monitor" + "AzurePolicy", + "APIM" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage.", - "waf": "Operations" + "subcategory": "Best practices", + "text": "Use Named Values to store common values that can be used in policies" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "97be9951-9048-4384-9c98-6cb2913156a1", - "id": "F03.16", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", + "checklist": "Azure API Management Review", + "guid": "beae759e-4ddb-4326-bf26-47f87d3454b6", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-deploy-multi-region", "services": [ - "Monitor" + "ASR", + "APIM" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor alerts for the generation of operational alerts.", - "waf": "Operations" + "subcategory": "Business continuity and disaster recovery", + "text": "Deploy to multiple Azure regions" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "859c3900-4514-41eb-b010-475d695abd74", - "id": "F03.17", - "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", + "checklist": "Azure API Management Review", + "guid": "9c8d1664-dd9a-49d4-bd83-950af0af4044", + "link": "https://learn.microsoft.com/azure/api-management/high-availability", "services": [ - "Monitor" + "ASR", + "APIM" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied", - "waf": "Operations" + "subcategory": "Business continuity and disaster recovery", + "text": "Deploy at least two scale units spread over two availability zones per region for best availability and performance" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", - "id": "F03.18", - "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", + "checklist": "Azure API Management Review", + "guid": "8d2db6e8-85c6-4118-a52c-ae76a4f27934", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#service-native-backup-capability", "services": [ - "Monitor" + "ASR", + "Backup", + "APIM" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Consider supported regions for linked Log Analytics workspace and automation accounts", - "waf": "Operations" + "severity": "High", + "subcategory": "Business continuity and disaster recovery", + "text": "Ensure there is an automated backup routine" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", - "id": "F04.01", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", + "checklist": "Azure API Management Review", + "guid": "f96ddac5-77ec-4fa9-8833-4327f052059e", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-cache-external", "services": [ - "VM", - "AzurePolicy" + "AzurePolicy", + "APIM" ], "severity": "Medium", - "subcategory": "Operational compliance", - "text": "Use Azure policies to automatically deploy software configurations through VM extensions and enforce a compliant baseline VM configuration.", - "waf": "Security" + "subcategory": "Performance and scalability", + "text": "Consider using a external cache policy for APIs that can benefit from caching", + "training": "https://learn.microsoft.com/training/modules/improve-api-performance-with-apim-caching-policy/" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "description": "Azure Policy's guest configuration features can audit and remediate machine settings (e.g., OS, application, environment) to ensure resources align with expected configurations, and Update Management can enforce patch management for VMs.", - "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", - "id": "F04.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", + "checklist": "Azure API Management Review", + "guid": "8210699f-8d43-45c2-8f19-57e54134bd8f", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-log-event-hubs", "services": [ - "VM", + "EventHubs", "AzurePolicy", - "Monitor" + "APIM" ], - "severity": "Medium", - "subcategory": "Operational compliance", - "text": "Monitor VM security configuration drift via Azure Policy.", - "waf": "Security" + "severity": "Low", + "subcategory": "Performance and scalability", + "text": "If you need to log at high performance levels, consider Event Hubs policy" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", - "id": "F05.01", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", + "checklist": "Azure API Management Review", + "guid": "121bfc39-fa7b-4096-b93b-ab56c1bc0bed", + "link": "https://learn.microsoft.com/azure/api-management/api-management-sample-flexible-throttling", "services": [ - "VM", - "ASR", - "ACR" + "AzurePolicy", + "APIM" ], "severity": "Medium", - "subcategory": "Protect and Recover", - "text": "Use Azure Site Recovery for Azure-to-Azure Virtual Machines disaster recovery scenarios. This enables you to replicate workloads across regions.", - "waf": "Operations" + "subcategory": "Performance and scalability", + "text": "Apply throttling policies to control the number of requests per second", + "training": "https://learn.microsoft.com/training/modules/protect-apis-on-api-management/" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", - "id": "F05.02", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", + "checklist": "Azure API Management Review", + "guid": "bb5f356b-3daf-47a2-a9ee-867a8100bbd5", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-autoscale", "services": [ - "ASR" + "APIM" ], "severity": "Medium", - "subcategory": "Protect and Recover", - "text": "Ensure to use and test native PaaS service disaster recovery capabilities.", - "waf": "Operations" + "subcategory": "Performance and scalability", + "text": "Configure autoscaling to scale out the number of instances when the load increases" }, { "category": "Management", - "checklist": "Azure Landing Zone Review", - "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", - "id": "F05.03", - "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", + "checklist": "Azure API Management Review", + "guid": "84b94abb-59b6-4b9d-8587-3413669468e8", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-provision-self-hosted-gateway", "services": [ - "Backup" + "APIM" ], "severity": "Medium", - "subcategory": "Protect and Recover", - "text": "Use Azure-native backup capabilities, or an Azure-compatible, 3rd-party backup solution.", - "waf": "Operations" + "subcategory": "Performance and scalability", + "text": "Deploy self-hosted gateways where Azure doesn't have a region close to the backend APIs." }, { - "ammp": true, - "category": "Management ", - "checklist": "Azure Landing Zone Review", - "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", - "id": "F06.01", - "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "d7941d4a-7b6f-458f-8714-2f8f8c059ad4", + "link": "https://learn.microsoft.com/azure/api-management/api-management-error-handling-policies", "services": [ - "VM" + "AzurePolicy", + "APIM" ], - "severity": "High", - "subcategory": "Fault Tolerance", - "text": "Leverage Availability Zones for your VMs in regions where they are supported.", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Development best practices", + "text": "Implement an error handling policy at the global level" }, { - "ammp": true, - "category": "Management ", - "checklist": "Azure Landing Zone Review", - "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", - "id": "F06.02", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability", + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "0b0c0765-ff37-4369-90bd-3eb23ce71b08", + "link": "https://learn.microsoft.com/azure/api-management/set-edit-policies?tabs=form#use-base-element-to-set-policy-evaluation-order", "services": [ - "VM" + "AzurePolicy", + "APIM" ], - "severity": "High", - "subcategory": "Fault Tolerance", - "text": "Avoid running a production workload on a single VM.", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Development best practices", + "text": "Ensure all APIs policies include a element." }, { - "category": "Management ", - "checklist": "Azure Landing Zone Review", - "guid": "84101f59-1941-4195-a270-e28034290e3a", - "id": "F06.03", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "a5c45b03-93b6-42fe-b16b-8fccb6a79902", + "link": "https://learn.microsoft.com/azure/api-management/policy-fragments", "services": [ - "LoadBalancer", + "AzurePolicy", "ACR", - "AppGW" + "APIM" ], "severity": "Medium", - "subcategory": "Fault Tolerance", - "text": "Azure Load Balancer and Application Gateway distribute incoming network traffic across multiple resources.", - "waf": "Reliability" - }, - { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", - "id": "G01.01", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", - "services": [], - "severity": "Medium", - "subcategory": "Access control", - "text": "Determine the incident response plan for Azure services before allowing it into production.", - "waf": "Security" + "subcategory": "Development best practices", + "text": "Use Policy Fragments to avoid repeating same policies definitions across multiple APIs" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "01365d38-e43f-49cc-ad86-8266abca264f", - "id": "G01.02", - "link": "https://www.microsoft.com/security/business/zero-trust", - "services": [], + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "c3818a95-6ff3-4474-88dc-e809b46dad6a", + "link": "https://learn.microsoft.com/azure/api-management/monetization-support", + "services": [ + "APIM" + ], "severity": "Medium", - "subcategory": "Access control", - "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate.", - "waf": "Security" + "subcategory": "Monetization", + "text": "If you are planning to monetize your APIs, review the 'monetization support' article for best practices" }, { - "ammp": true, - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "5017f154-e3ab-4369-9829-e7e316183687", - "id": "G02.01", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview", + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "a7d0840a-c8c4-4e83-adec-5ca578eb4049", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-use-azure-monitor#resource-logs", "services": [ - "AKV" + "Monitor", + "APIM" ], "severity": "High", - "subcategory": "Encryption and keys", - "text": "Use Azure Key Vault to store your secrets and credentials", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Enable Diagnostics Settings to export logs to Azure Monitor" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "graph": "ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1)", - "guid": "a0477a20-9945-4bda-9333-4f2491163418", - "id": "G02.02", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "8691fa38-45ed-4299-a247-fecd98d35deb", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-app-insights", "services": [ - "AKV" + "Monitor", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets.", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Enable Application Insights for more detailed telemetry" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", - "id": "G02.03", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Governance", + "checklist": "Azure API Management Review", + "guid": "55fd27bb-76ac-4a91-bc37-049e885be6b7", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-use-azure-monitor", "services": [ - "AzurePolicy", - "AKV" + "Monitor", + "APIM" ], - "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects.", - "waf": "Security" + "severity": "High", + "subcategory": "Monitoring", + "text": "Configure alerts on the most critical metrics" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "dc055bcf-619e-48a1-9f98-879525d62688", - "id": "G02.04", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Identity and Access Management", + "checklist": "Azure API Management Review", + "guid": "39460bdb-156f-4dc2-a87f-1e8c11ab0998", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#certificate-management-in-azure-key-vault", "services": [ - "RBAC", + "AKV", "Entra", - "AKV" + "APIM" ], - "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Follow a least privilege model by limiting authorization to permanently delete keys, secrets, and certificates to specialized custom Microsoft Entra ID roles.", - "waf": "Security" + "severity": "High", + "subcategory": "Data protection", + "text": "Ensure that custom SSL certificates are stored an Azure Key Vault so they can be securely accessed and updated" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", - "id": "G02.05", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Identity and Access Management", + "checklist": "Azure API Management Review", + "guid": "e9217997-5f6c-479d-8576-8f2adf706ec8", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#azure-ad-authentication-required-for-data-plane-access", "services": [ - "AKV" + "Entra", + "APIM" ], - "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Automate the certificate management and renewal process with public certificate authorities to ease administration.", - "waf": "Security" + "severity": "High", + "subcategory": "Identity", + "text": "Protect incoming requests to APIs (data plane) with Azure AD" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "913156a1-2476-4e49-b541-acdce979377b", - "id": "G02.06", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Identity and Access Management", + "checklist": "Azure API Management Review", + "guid": "5e5f64ba-c90e-480e-8888-398d96cf0bfb", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-aad", "services": [ - "AKV" + "Entra", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Establish an automated process for key and certificate rotation.", - "waf": "Security" + "subcategory": "Identity", + "text": "Use Azure AD to authenticate users in the Developer Portal" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", - "id": "G02.07", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Identity and Access Management", + "checklist": "Azure API Management Review", + "guid": "f8e574ce-280f-49c8-b2ef-68279b081cf3", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-create-groups", "services": [ - "VNet", - "AKV", - "PrivateLink" + "Entra", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Enable firewall and virtual network service endpoint or private endpoint on the vault to control access to the key vault.", - "waf": "Security" + "subcategory": "Privileged access", + "text": "Create appropriate groups to control the visibility of the products" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", - "id": "G02.08", - "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", + "category": "Network Topology and Connectivity", + "checklist": "Azure API Management Review", + "guid": "cd45c90e-7690-4753-930b-bf290c69c074", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#virtual-network-integration", "services": [ - "Entra", - "AKV", - "Monitor" + "VNet", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Use the platform-central Azure Monitor Log Analytics workspace to audit key, certificate, and secret usage within each instance of Key Vault.", - "waf": "Security" + "subcategory": "Security", + "text": "Deploy the service within a Virtual Network (VNET)" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", - "id": "G02.09", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Network Topology and Connectivity", + "checklist": "Azure API Management Review", + "guid": "02661582-b3d1-48d1-9d7b-c6a918a0ca33", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#network-security-group-support", "services": [ - "AzurePolicy", - "AKV" + "Monitor", + "VNet", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Delegate Key Vault instantiation and privileged access and use Azure Policy to enforce a consistent compliant configuration.", - "waf": "Security" + "subcategory": "Security", + "text": "Deploy network security groups (NSG) to your subnets to restrict or monitor traffic" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "16183687-a047-47a2-8994-5bda43334f24", - "id": "G02.10", - "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", + "category": "Network Topology and Connectivity", + "checklist": "Azure API Management Review", + "guid": "67437a28-2721-4a2c-becd-caa54c8237a5", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#azure-private-link", "services": [ - "AKV" + "VNet", + "PrivateLink", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required.", - "waf": "Security" + "subcategory": "Security", + "text": "Deploy Private Endpoints to filter incoming traffic when VNET is not used" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "91163418-2ba5-4275-8694-4008be7d7e48", - "id": "G02.11", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", - "services": [ - "AKV" + "category": "Network Topology and Connectivity", + "checklist": "Azure API Management Review", + "guid": "d698adbd-3288-44cb-b10a-9b572da395ae", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#disable-public-network-access", + "services": [ + "APIM" ], - "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "Use an Azure Key Vault per application per environment per region.", - "waf": "Security" + "severity": "High", + "subcategory": "Security", + "text": "Disable Public Network Access" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "25d62688-6d70-4ba6-a97b-e99519048384", - "id": "G02.12", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Network Topology and Connectivity", + "checklist": "Azure API Management Review", + "guid": "7519e385-a88b-4d34-966b-6269d686e890", + "link": "https://learn.microsoft.com/azure/api-management/front-door-api-management", "services": [ - "ASR", - "ACR", - "AKV" + "FrontDoor", + "APIM" ], "severity": "Medium", - "subcategory": "Encryption and keys", - "text": "If you want to bring your own keys, this might not be supported across all considered services. Implement relevant mitigation so that inconsistencies don't hinder desired outcomes. Choose appropriate region pairs and disaster recovery regions that minimize latency.", - "waf": "Security" + "subcategory": "Connectivity", + "text": "Use Azure Front Door for multi-region deployment" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", - "id": "G03.01", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", + "category": "Platform automation and DevOps", + "checklist": "Azure API Management Review", + "guid": "0674d750-0c6f-4ac0-8717-ceec04d0bdbd", + "link": "https://learn.microsoft.com/azure/api-management/automation-manage-api-management", "services": [ - "Entra" + "APIM" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Use Microsoft Entra ID reporting capabilities to generate access control audit reports.", - "waf": "Security" + "subcategory": "Automation", + "text": "Simplify management with PowerShell automation scripts" }, { - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", - "id": "G03.02", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", + "category": "Platform automation and DevOps", + "checklist": "Azure API Management Review", + "guid": "c385bfcd-49fd-4786-81ba-cedbb4c57345", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/app-platform/api-management/platform-automation-and-devops#design-recommendations", "services": [ - "ARS", - "Storage", - "Monitor" + "Entra", + "APIM" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Export Azure activity logs to Azure Monitor Logs for long-term data retention. Export to Azure Storage for long-term storage beyond two years, if necessary.", - "waf": "Security" + "subcategory": "Best practices", + "text": "Review DevOps best practices from the Cloud Adaption Framework APIM Landing Zone Accelerator" }, { - "ammp": true, - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "09945bda-4333-44f2-9911-634182ba5275", - "id": "G03.03", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", + "category": "Platform automation and DevOps", + "checklist": "Azure API Management Review", + "guid": "6c3a27c0-197f-426c-9ffa-86fed51d9ab6", + "link": "https://learn.microsoft.com/azure/api-management/visual-studio-code-tutorial", "services": [ - "Subscriptions", - "Defender" + "Entra", + "APIM" ], - "severity": "High", - "subcategory": "Operations", - "text": "Enable Defender Cloud Security Posture Management for all subscriptions.", - "waf": "Security" + "severity": "Medium", + "subcategory": "Best practices", + "text": "Promote usage of Visual Studio Code APIM extension for faster API development" }, { - "ammp": true, - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", - "id": "G03.04", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", + "category": "Platform automation and DevOps", + "checklist": "Azure API Management Review", + "guid": "354f1c03-8112-4965-85ad-c0074bddf231", + "link": "https://learn.microsoft.com/azure/api-management/devops-api-development-templates", "services": [ - "Subscriptions", - "Defender" + "APIM" ], - "severity": "High", - "subcategory": "Operations", - "text": "Enable a Defender Cloud Workload Protection Plan for Servers on all subscriptions.", - "waf": "Security" + "severity": "Medium", + "subcategory": "DevOps", + "text": "Implement DevOps and CI/CD in your workflow" }, { - "ammp": true, "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", - "id": "G03.05", - "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", + "checklist": "Azure API Management Review", + "guid": "b6439493-426a-45f3-9697-cf65baee208d", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-mutual-certificates-for-clients", "services": [ - "Subscriptions", - "Defender" + "APIM" ], - "severity": "High", - "subcategory": "Operations", - "text": "Enable Defender Cloud Workload Protection Plans for Azure Resources on all subscriptions.", - "waf": "Security" - }, - { - "ammp": true, - "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", - "id": "G03.06", - "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection", - "services": [], - "severity": "High", - "subcategory": "Operations", - "text": "Enable Endpoint Protection on IaaS Servers.", - "waf": "Security" + "severity": "Medium", + "subcategory": "APIs", + "text": "Secure APIs using client certificate authentication" }, { "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", - "id": "G03.07", - "link": "https://learn.microsoft.com/azure/security-center/", + "checklist": "Azure API Management Review", + "guid": "2a67d143-1033-4c0a-8732-680896478f08", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-mutual-certificates", "services": [ - "Defender", - "Monitor" + "APIM" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud.", - "waf": "Security" + "subcategory": "APIs", + "text": "Secure backend services using client certificate authentication" }, { "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", - "id": "G03.08", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "checklist": "Azure API Management Review", + "guid": "074435f5-4a46-41ac-b521-d6114cb5d845", + "link": "https://learn.microsoft.com/azure/api-management/mitigate-owasp-api-threats", "services": [ - "Entra", - "Monitor" + "APIM" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace.", - "waf": "Security" + "subcategory": "APIs", + "text": "Review 'Recommendations to mitigate OWASP API Security Top 10 threats' article and check what is applicable to your APIs" }, { - "ammp": true, "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", - "id": "G04.01", - "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", + "checklist": "Azure API Management Review", + "guid": "5507c4b8-a7f8-41d6-9661-418c987100c9", + "link": "https://learn.microsoft.com/azure/api-management/authorizations-overview", "services": [ - "Storage" + "APIM" ], - "severity": "High", - "subcategory": "Overview", - "text": "Secure transfer to storage accounts should be enabled", - "waf": "Security" + "severity": "Medium", + "subcategory": "APIs", + "text": "Use Authorizations feature to simplify management of OAuth 2.0 token for your backend APIs" }, { - "ammp": true, "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", - "id": "G04.02", - "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", + "checklist": "Azure API Management Review", + "guid": "2deee033-b906-4bc2-9f26-c8d3699fe091", + "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-manage-protocols-ciphers", "services": [ - "Storage" + "APIM" ], "severity": "High", - "subcategory": "Overview", - "text": "Enable container soft delete for the storage account to recover a deleted container and its contents.", - "waf": "Security" + "subcategory": "Ciphers", + "text": "Use the latest TLS version when encrypting information in transit. Disable outdated and unnecessary protocols and ciphers when possible." }, { - "ammp": true, "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "6f704104-85c1-441f-96d3-c9819911645e", - "id": "G05.01", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning", + "checklist": "Azure API Management Review", + "guid": "f8af3d94-1d2b-4070-846f-849197524258", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#im-8-restrict-the-exposure-of-credential-and-secrets", "services": [ - "Entra" + "AKV", + "APIM" ], "severity": "High", - "subcategory": "Secure privileged access", - "text": "Separate privileged admin accounts for Azure administrative tasks.", - "waf": "Security" + "subcategory": "Data protection", + "text": "Ensure that secrets (Named values) are stored an Azure Key Vault so they can be securely accessed and updated" }, { "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", - "id": "G06.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", - "services": [], + "checklist": "Azure API Management Review", + "guid": "791abd8b-7706-4e31-9569-afefde724be3", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#managed-identities", + "services": [ + "Entra", + "APIM" + ], "severity": "Medium", - "subcategory": "Service enablement framework", - "text": "Plan how new azure services will be implemented", - "waf": "Security" + "subcategory": "Identities", + "text": "Use managed identities to authenticate to other Azure resources whenever possible" }, { "category": "Security", - "checklist": "Azure Landing Zone Review", - "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", - "id": "G06.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", - "services": [], - "severity": "Medium", - "subcategory": "Service enablement framework", - "text": "Plan how service request will be fulfilled for Azure services", - "waf": "Security" - }, - { - "ammp": true, - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", - "id": "H01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", - "services": [], - "severity": "High", - "subcategory": "DevOps Team Topologies", - "text": "Ensure you have a cross functional DevOps Platform Team to build, manage and maintain your Azure Landing Zone architecture.", - "waf": "Operations" - }, - { - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", - "id": "H01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", - "services": [], - "severity": "Low", - "subcategory": "DevOps Team Topologies", - "text": "Aim to define functions for Azure Landing Zone Platform team.", - "waf": "Operations" - }, - { - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", - "id": "H01.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", - "services": [ - "RBAC" - ], - "severity": "Low", - "subcategory": "DevOps Team Topologies", - "text": "Aim to define functions for application workload teams to be self-sufficient and not require DevOps Platform Team support. Achieve this through the use of custom RBAC role.", - "waf": "Operations" - }, - { - "ammp": true, - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "165eb5e9-b434-448a-9e24-178632186212", - "id": "H01.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", - "services": [], - "severity": "High", - "subcategory": "DevOps Team Topologies", - "text": "Use a CI/CD pipeline to deploy IaC artifacts and ensure the quality of your deployment and Azure environments.", - "waf": "Operations" - }, - { - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", - "id": "H01.05", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", - "services": [], - "severity": "Medium", - "subcategory": "DevOps Team Topologies", - "text": "Include unit tests for IaC and application code as part of your build process.", - "waf": "Operations" - }, - { - "ammp": true, - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", - "id": "H01.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", - "services": [ - "VM", - "AKV" - ], - "severity": "High", - "subcategory": "DevOps Team Topologies", - "text": "Use Key Vault secrets to avoid hard-coding sensitive information such as credentials (virtual machines user passwords), certificates or keys.", - "waf": "Operations" - }, - { - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", - "id": "H01.07", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", - "services": [ - "Storage" - ], - "severity": "Low", - "subcategory": "DevOps Team Topologies", - "text": "Implement automation for File > New > Landing Zone for applications and workloads.", - "waf": "Operations" - }, - { - "ammp": true, - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", - "id": "H02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", - "services": [], - "severity": "High", - "subcategory": "Development Lifecycle", - "text": "Ensure a version control system is used for source code of applications and IaC developed. Microsoft recommends Git.", - "waf": "Operations" - }, - { - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", - "id": "H02.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", - "services": [], - "severity": "Low", - "subcategory": "Development Lifecycle", - "text": "Follow a branching strategy to allow teams to collaborate better and efficiently manage version control of IaC and application Code. Review options such as Github Flow.", - "waf": "Operations" - }, - { - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", - "id": "H02.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", - "services": [], - "severity": "Medium", - "subcategory": "Development Lifecycle", - "text": "Adopt a pull request strategy to help keep control of code changes merged into branches.", - "waf": "Operations" - }, - { - "ammp": true, - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", - "id": "H03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", - "services": [], - "severity": "High", - "subcategory": "Development Strategy", - "text": "Leverage Declarative Infrastructure as Code Tools such as Azure Bicep, ARM Templates or Terraform to build and maintain your Azure Landing Zone architecture. Both from a Platform and Application workload perspective.", - "waf": "Operations" - }, - { - "ammp": true, - "category": "Platform Automation and DevOps", - "checklist": "Azure Landing Zone Review", - "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", - "id": "H04.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", - "services": [], - "severity": "High", - "subcategory": "Security", - "text": "Integrate security into the already combined process of development and operations in DevOps to mitigate risks in the innovation process.", - "waf": "Operations" + "checklist": "Azure API Management Review", + "guid": "220c4ca6-6688-476b-b2b5-425a78e6fb87", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#ns-6-deploy-web-application-firewall", + "services": [ + "WAF", + "Entra", + "AppGW", + "APIM" + ], + "severity": "High", + "subcategory": "Network", + "text": "Use web application firewall (WAF) by deploying Application Gateway in front of APIM" }, { "category": "BCDR", @@ -3262,8 +2487,8 @@ "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-2-encrypt-backup-data", "services": [ "SQL", - "Backup", - "AKV" + "AKV", + "Backup" ], "severity": "Medium", "subcategory": "Azure Key Vault", @@ -3279,8 +2504,8 @@ "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-1-ensure-regular-automated-backups", "services": [ "SQL", - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "Medium", "subcategory": "Backup", @@ -3296,8 +2521,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/automated-backups-overview?tabs=single-database&view=azuresql#backup-storage-redundancy", "services": [ "SQL", - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "Low", "subcategory": "Backup", @@ -3358,8 +2583,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-configure", "services": [ "SQL", - "EventHubs", - "Defender" + "Defender", + "EventHubs" ], "severity": "High", "subcategory": "Advanced Threat Protection", @@ -3375,8 +2600,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/azure-defender-for-sql?view=azuresql#enable-microsoft-defender-for-sql ", "services": [ "SQL", - "Subscriptions", - "Defender" + "Defender", + "Subscriptions" ], "severity": "High", "subcategory": "Defender for Azure SQL", @@ -3457,8 +2682,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#control-access-of-application-users-to-sensitive-data-through-encryption", "services": [ "SQL", - "Storage", - "AKV" + "AKV", + "Storage" ], "severity": "Low", "subcategory": "Column Encryption", @@ -3474,8 +2699,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-create-server", "services": [ "SQL", - "Backup", - "Storage" + "Storage", + "Backup" ], "severity": "High", "subcategory": "Transparent Data Encryption", @@ -3538,8 +2763,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#central-management-for-identities", "services": [ "SQL", - "Entra", - "Monitor" + "Monitor", + "Entra" ], "severity": "Medium", "subcategory": "Azure Active Directory", @@ -3570,11 +2795,11 @@ "id": "G02.01", "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", "services": [ - "RBAC", - "Entra", "AKV", "SQL", - "ACR" + "Entra", + "ACR", + "RBAC" ], "severity": "Low", "subcategory": "Managed Identities", @@ -3701,12 +2926,12 @@ "id": "I01.02", "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", "services": [ - "EventHubs", - "Storage", "Monitor", + "Storage", "Backup", + "SQL", "Entra", - "SQL" + "EventHubs" ], "severity": "Low", "subcategory": "Auditing", @@ -3721,11 +2946,11 @@ "id": "I01.03", "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", "services": [ - "EventHubs", - "Storage", "Monitor", + "Storage", "SQL", - "Subscriptions" + "Subscriptions", + "EventHubs" ], "severity": "Medium", "subcategory": "Auditing", @@ -3805,8 +3030,8 @@ "link": "https://learn.microsoft.com/azure/azure-sql/database/connectivity-architecture", "services": [ "SQL", - "AzurePolicy", - "PrivateLink" + "PrivateLink", + "AzurePolicy" ], "severity": "Low", "subcategory": "Connectivity", @@ -3872,9 +3097,9 @@ "services": [ "Monitor", "VNet", - "Firewall", + "SQL", "PrivateLink", - "SQL" + "Firewall" ], "severity": "Medium", "subcategory": "Private Access", @@ -4067,11 +3292,11 @@ "id": "A01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "services": [ - "FrontDoor", - "AKV" + "AKV", + "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "If you use customer-managed TLS certificates with Azure Front Door, use the 'Latest' certificate version. Reduce the risk of outages caused by manual certificate renewal.", "waf": "Operations" }, @@ -4099,7 +3324,7 @@ "AppGW" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - App Gateway", "text": "Ensure you are using Application Gateway v2 SKU", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Security" @@ -4115,14 +3340,14 @@ "LoadBalancer" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Load Balancer", "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", "waf": "Security" }, { "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", - "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", "id": "A01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", @@ -4131,8 +3356,8 @@ "AppGW" ], "severity": "Medium", - "subcategory": "App delivery", - "text": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26", + "subcategory": "App delivery - App Gateway", + "text": "Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Security" }, @@ -4144,15 +3369,15 @@ "id": "A01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "NVA", "VNet", "AppGW", - "Entra", "WAF", - "Subscriptions" + "Entra", + "Subscriptions", + "NVA" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - App Gateway", "text": "Deploy Azure Application Gateway v2 or partner NVAs used for proxying inbound HTTP(S) connections within the landing-zone virtual network and with the apps that they're securing.", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Security" @@ -4167,7 +3392,7 @@ "DDoS" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - App Gateway", "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Security" @@ -4175,50 +3400,81 @@ { "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", "id": "A01.08", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "services": [ - "FrontDoor", - "AzurePolicy", - "WAF" - ], + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "services": [], "severity": "Medium", - "subcategory": "App delivery", - "text": "Use Azure Front Door with WAF policies to deliver and help protect global HTTP/S apps that span multiple Azure regions.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "subcategory": "App delivery - App Gateway", + "text": "Configure autoscaling with a minimum amount of instances of two.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", - "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", "id": "A01.09", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", "services": [ - "FrontDoor", - "AzurePolicy", - "AppGW", - "WAF" + "ACR", + "AppGW" ], "severity": "Medium", - "subcategory": "App delivery", - "text": "When using Front Door and Application Gateway to help protect HTTP/S apps, use WAF policies in Front Door. Lock down Application Gateway to receive traffic only from Front Door.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "waf": "Security" + "subcategory": "App delivery - App Gateway", + "text": "Deploy Application Gateway across Availability Zones", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Reliability" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "WAF", + "FrontDoor", + "AzurePolicy" + ], + "severity": "Medium", + "subcategory": "App delivery - Front Door", + "text": "Use Azure Front Door with WAF policies to deliver and help protect global HTTP/S apps that span multiple Azure regions.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Application Delivery Networking", + "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "A01.11", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "services": [ + "AzurePolicy", + "WAF", + "FrontDoor", + "AppGW" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "When using Front Door and Application Gateway to help protect HTTP/S apps, use WAF policies in Front Door. Lock down Application Gateway to receive traffic only from Front Door.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "ammp": true, "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "A01.10", + "id": "A01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ "TrafficManager" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Traffic Manager", "text": "Use Traffic Manager to deliver global apps that span protocols other than HTTP/S.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Reliability" @@ -4227,7 +3483,7 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "A01.11", + "id": "A01.13", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "services": [ "AVD", @@ -4243,7 +3499,7 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "A01.12", + "id": "A01.14", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "services": [ "Entra" @@ -4260,15 +3516,15 @@ "checklist": "Azure Application Delivery Networking", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "A01.13", + "id": "A01.15", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "services": [ - "FrontDoor", "Storage", - "WAF" + "WAF", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", "waf": "Security" }, @@ -4277,14 +3533,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "A01.14", + "id": "A01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "services": [ - "FrontDoor", - "TrafficManager" + "TrafficManager", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", "waf": "Security" }, @@ -4293,13 +3549,13 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "A01.15", + "id": "A01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "services": [ "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use the same domain name on Azure Front Door and your origin. Mismatched host names can cause subtle bugs.", "waf": "Security" }, @@ -4307,13 +3563,13 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "A01.16", + "id": "A01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "services": [ "FrontDoor" ], "severity": "Low", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", "waf": "Performance" }, @@ -4321,13 +3577,13 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "A01.17", + "id": "A01.19", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "services": [ "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Select good health probe endpoints for Azure Front Door. Consider building health endpoints that check all of your application's dependencies.", "waf": "Reliability" }, @@ -4335,13 +3591,13 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "A01.18", + "id": "A01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "services": [ "FrontDoor" ], "severity": "Low", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use HEAD health probes with Azure Front Door, to reduce the traffic that Front Door sends to your application.", "waf": "Performance" }, @@ -4351,13 +3607,13 @@ "checklist": "Azure Application Delivery Networking", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "A01.19", + "id": "A01.21", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "services": [ "LoadBalancer" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Load Balancer", "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", "waf": "Reliability" }, @@ -4366,15 +3622,15 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "A01.20", + "id": "A01.22", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "services": [ - "FrontDoor", "AKV", + "FrontDoor", "Cost" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use managed TLS certificates with Azure Front Door. Reduce operational cost and risk of outages due to certificate renewals.", "waf": "Operations" }, @@ -4382,29 +3638,29 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "A01.21", + "id": "A01.23", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Define your Azure Front Door WAF configuration as code. By using code, you can more easily adopt new ruleset versions and gain additional protection.", "waf": "Operations" }, { "ammp": true, - "category": "Network topology and connectivity", + "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "A02.01", + "id": "A01.24", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "services": [ "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use end-to-end TLS with Azure Front Door. Use TLS for connections from your clients to Front Door, and from Front Door to your origin.", "waf": "Security" }, @@ -4412,13 +3668,13 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "A02.02", + "id": "A01.25", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "services": [ "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use HTTP to HTTPS redirection with Azure Front Door. Support older clients by redirecting them to an HTTPS request automatically.", "waf": "Security" }, @@ -4427,14 +3683,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "A02.03", + "id": "A01.26", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", "waf": "Security" }, @@ -4443,14 +3699,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "A02.04", + "id": "A01.27", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", "waf": "Security" }, @@ -4459,14 +3715,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "A02.05", + "id": "A01.28", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", "waf": "Security" }, @@ -4475,14 +3731,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "A02.06", + "id": "A01.29", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", "waf": "Security" }, @@ -4491,14 +3747,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "A02.07", + "id": "A01.30", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "High", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", "waf": "Security" }, @@ -4506,14 +3762,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "A02.08", + "id": "A01.31", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use the latest Azure Front Door WAF ruleset versions. Ruleset updates are regularly updated to take account of the current threat landscape.", "waf": "Security" }, @@ -4521,14 +3777,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "A02.09", + "id": "A01.32", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Add rate limiting to the Azure Front Door WAF. Rate limiting blocks clients accidentally or intentionally sending large amounts of traffic in a short period of time.", "waf": "Security" }, @@ -4536,14 +3792,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "A02.10", + "id": "A01.33", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Use a high threshold for Azure Front Door WAF rate limits. High rate limit thresholds avoid blocking legitimate traffic, while still providing protection against extremely high numbers of requests that might overwhelm your infrastructure. ", "waf": "Security" }, @@ -4551,14 +3807,14 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "A02.11", + "id": "A01.34", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "Low", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Geo-filter traffic by using the Azure Front Door WAF. Allow traffic only from expected regions, and block traffic from other regions.", "waf": "Security" }, @@ -4566,16886 +3822,17674 @@ "category": "Network Topology and Connectivity", "checklist": "Azure Application Delivery Networking", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "A02.12", + "id": "A01.35", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "services": [ - "FrontDoor", - "WAF" + "WAF", + "FrontDoor" ], "severity": "Medium", - "subcategory": "App delivery", + "subcategory": "App delivery - Front Door", "text": "Specify the unknown (ZZ) location when geo-filtering traffic with the Azure Front Door WAF. Avoid accidentally blocking legitimate requests when IP addresses can't be geo-matched.", "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "9f519499-5820-4060-88fe-cab4538c9dd0", - "id": "01.01.01", - "link": "https://learn.microsoft.com/windows-server/storage/storage-spaces/storage-spaces-direct-hardware-requirements", - "services": [ - "Storage" - ], + "category": "Application Deployment", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "6d8e32a8-3892-479d-a40b-10f6b4f6f298", + "link": "https://learn.microsoft.com/azure/spring-apps/concepts-blue-green-deployment-strategies", + "services": [], "severity": "Medium", - "subcategory": "Physical", - "text": "All planned storage pools should use direct-attached storage (SATA, SAS, NVMe)", - "waf": "Performance" + "subcategory": "DevOps", + "text": "Azure Spring Apps permits two deployments for every app, only one of which receives production traffic. You can achieve zero downtime with blue green deployment strategies. Blue green deployment is only available in Standard and Enterprise tiers. You could automate deployment using CI/CD with ADO/GitHub actions", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "f7c015e0-7d97-4283-b006-567afeb2b5ca", - "id": "01.01.02", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/drive-symmetry-considerations#understand-capacity-imbalance", + "category": "BC and DR", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "fbcb40ac-9480-4a6d-bcf4-8081252a6716", + "link": "https://learn.microsoft.com/azure/architecture/web-apps/spring-apps/architectures/spring-apps-multi-region", "services": [ - "ACR", - "Storage" + "TrafficManager", + "FrontDoor", + "ASR" ], "severity": "Medium", - "subcategory": "Physical", - "text": "Disks are symmetrical across all nodes", - "waf": "Performance" + "subcategory": "Disaster Recovery", + "text": "Azure Spring Apps instances could be created in multiple regions for your applications and traffic could be routed by Traffic Manager/Front Door.", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "f785b143-2c1e-4466-9baa-dde8ba4c7aaa", - "id": "01.02.01", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/fault-tolerance#parity", + "category": "BC and DR", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "ff1ae6a7-9301-4feb-9d11-56cd72f1d4ef", + "link": "https://learn.microsoft.com/azure/reliability/reliability-spring-apps", "services": [ - "Backup", - "Storage" + "ACR" ], "severity": "Medium", - "subcategory": "S2D", - "text": "Parity type disk redundancy should only be used for low I/O volumes (backup/archive)", - "waf": "Performance" + "subcategory": "High Availability", + "text": "In supported region, Azure Spring Apps can be deployed as zone redundant, which means that instances are automatically distributed across availability zones. This feature is only available in Standard and Enterprise tiers.", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "8a705965-9840-43cc-93b3-06d089406bb4", - "id": "01.02.02", - "link": "https://learn.microsoft.com/windows-server/storage/storage-spaces/storage-spaces-direct-hardware-requirements#physical-deployments", - "services": [ - "Storage" - ], + "category": "BC and DR", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "ffc735ad-fbb1-4802-b43f-ad6387c4c066", + "link": "https://learn.microsoft.com/azure/spring-apps/concept-understand-app-and-deployment", + "services": [], "severity": "Medium", - "subcategory": "S2D", - "text": "Ensure there at least 2 capacity disks with available capacity in the Storage Pool", + "subcategory": "High Availability", + "text": "Use more than 1 app instance for your apps", "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "2a4f629a-d623-4610-a8e3-d6fd66057d8e", - "id": "01.02.03", - "link": "https://learn.microsoft.com/windows-server/storage/storage-spaces/delimit-volume-allocation", + "category": "Operations", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "7504c230-6035-4183-95a5-85762acc6075", + "link": "https://learn.microsoft.com/azure/spring-apps/diagnostic-services", "services": [ - "Storage" + "Monitor" ], - "severity": "Low", - "subcategory": "S2D", - "text": "'Delimited allocation' has been considered to improve volume resiliency in a multi-node failure", + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Monitor Azure Spring Apps with logs, metrics and tracing. Integrate ASA with application insights and track failures and create workbooks.", "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "960eb9be-1f0f-4fc1-9b31-fcf1cf9e34e6", - "id": "01.02.04", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/plan-volumes#choosing-how-many-volumes-to-create", - "services": [ - "Storage" - ], + "category": "Operations", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "1eb48d58-3eec-4ef5-80b0-d2b0dde3f0c6", + "link": "https://learn.microsoft.com/azure/spring-apps/how-to-configure-enterprise-spring-cloud-gateway", + "services": [], "severity": "Medium", - "subcategory": "S2D", - "text": "CSVs are created in multiples of node count", - "waf": "Performance" + "subcategory": "Scalability", + "text": "Set up autoscaling in Spring Cloud Gateway", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "859ba2b9-a3a8-4ca1-bb61-165effbf1c03", - "id": "01.02.05", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/cache", - "services": [ - "Storage" - ], - "severity": "Medium", - "subcategory": "S2D", - "text": "If a cache tier is implemented, the number of capacity drives is a multiple of the number of cache drives", - "waf": "Performance" + "category": "Operations", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "97411607-b6fd-4335-99d1-9885faf4e392", + "link": "https://learn.microsoft.com/azure/spring-apps/how-to-setup-autoscale", + "services": [], + "severity": "Low", + "subcategory": "Scalability", + "text": "Enable autoscale for the apps with Standard consumption & dedicated plan.", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "d8a65f05-db06-461d-81dc-7899ad3f8f1e", - "id": "01.02.06", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/plan-volumes#reserve-capacity", - "services": [ - "Storage" - ], + "category": "Operations", + "checklist": "Azure Spring Apps Review", + "cost": 1, + "guid": "dfcaffd1-d27c-4ef2-998d-64c1df3a7ac3", + "link": "https://learn.microsoft.com/azure/spring-apps/overview", + "services": [], "severity": "Medium", - "subcategory": "S2D", - "text": "A minimum of 1 type of each disk type per node has been factored as a reserve disk", + "subcategory": "Support", + "text": "Use Enterprise plan for commercial support of spring boot for mission critical apps. With other tiers you get OSS support.", "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "description": "VMFleet is a tool that can be used to measure the performance of a storage subsystem, best used to baseline performance prior to workload deployment", - "guid": "9d138f1d-5363-476e-bbd7-acfa500bdc0c", - "id": "01.02.07", - "link": "https://github.com/microsoft/diskspd/wiki/VMFleet", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD control plane does not offer a financially backed service level agreement. We strive to attain at least 99.9% availability for the Azure Virtual Desktop service URLs. The availability of the session host virtual machines in your subscription is covered by the Virtual Machines SLA. Dependent resources/services and infrastructure availability must be also considered to properly satisfy global high-availability requirements.", + "guid": "56c57ba5-9119-4bf8-b8f5-c586c7d9cdc1", + "id": "A01.01", + "link": "https://azure.microsoft.com/support/legal/sla/virtual-desktop/v1_0/", "services": [ - "Storage" + "AVD", + "Subscriptions", + "VM", + "ASR" ], - "severity": "Low", - "subcategory": "S2D", - "text": "VMFleet has been run prior to workload deployment to baseline storage performance", - "waf": "Performance" + "severity": "High", + "subcategory": "Compute", + "text": "Determine the expected High Availability SLA for applications/desktops published through AVD", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "13c12e2a-c938-4dd1-9223-507d5e17f9c5", - "id": "01.03.01", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "'Active-Active' model can be achieved with multiple host pools in different regions. A single Host Pool with VMs from different regions is not recommended. If multiple pools for same users will be used, the problem of how to synchronize/replicate user profiles must be solved. FSLogix Cloud Cache could be used, but need to be carefully reviewed and planned, or customers can decide to do not synchronize/replicate at all. 'Active-Passive' can be achieved using Azure Site Recovery (ASR) or on-demand Pool deployment with automated mechanism. For a detailed discussion on multi-region BCDR, please read the companion article in the 'More Info' column and this FSLogix related page: https://learn.microsoft.com/fslogix/concepts-container-recovery-business-continuity.", + "guid": "6acc076e-f9b1-441a-a989-579e76b897e7", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/azure-virtual-desktop-multi-region-bcdr", "services": [ - "Storage" + "AVD", + "VM", + "Storage", + "ASR" ], "severity": "Medium", - "subcategory": "Host OS", - "text": "OS drives use a dedicated storage controller", + "subcategory": "Compute", + "text": "Assess Geo Disaster Recovery requirements for AVD Host Pools", "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Stack HCI Review", - "guid": "a631e7dc-8879-45bd-b0a7-e5927b805428", - "id": "01.03.02", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/use-csv-cache", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Before approaching Azure Virtual Desktop BCDR planning and design, it is important to initially consider which applications consumed through AVD are critical. You may want to separate them from non-critical apps and use a separate Host Pool with a different disaster recovery approach and capabilities.", + "guid": "10a7da7b-e996-46e1-9d3c-4ada97cc3d13", + "id": "A01.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Storage" + "AVD", + "ASR" ], - "severity": "Medium", - "subcategory": "Host OS", - "text": "CSV in-memory read caching is enabled and properly configured", - "waf": "Performance" + "severity": "Low", + "subcategory": "Compute", + "text": "Separate critical applications in different AVD Host Pools", + "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "c062cd9a-f1db-4f83-aab3-9cb03f56c140", - "id": "02.01.01", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/host-network-requirements#switch-embedded-teaming-set", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Each Host Pool can be deployed using Availability Zones (AZ) or Availability Set (AS). To maximize resiliency, usage of AZ is recommended: at Host Pool creation time you can decide to spread Host Pool Session Hosts across all available AZ. Usage of AS will not protect from single datacenter failure, then should be used only in regions where AZ are not available. More details on AZ and AVD in the companion article. For a comparison between AZ and AS you can read here: https://learn.microsoft.com/azure/virtual-machines/availability.", + "guid": "25ab225c-6f4e-4168-9fdd-dea8a4b7cdeb", + "id": "A01.04", + "link": "https://techcommunity.microsoft.com/t5/azure-virtual-desktop-blog/announcing-general-availability-of-support-for-azure/ba-p/3636262", "services": [ - "ACR" + "AVD", + "ACR", + "ASR" ], - "severity": "Medium", - "subcategory": "Host", - "text": "NICs are symmetrical across nodes", + "severity": "High", + "subcategory": "Compute", + "text": "Plan the best resiliency option for AVD Host Pool deployment", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "ea8054db-a558-4533-80c8-5d9cf447ba19", - "id": "02.01.02", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Backup can be used to protect Host Pool VMs. For Pooled Pools, this is not necessary since should be stateless. Instead, this option can be considered for Personal Host Pools.", + "guid": "4c61fc3f-c14e-4ea6-b69e-8d9a3eec218e", + "id": "A01.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Storage" + "ASR", + "AVD", + "VM", + "Backup" ], - "severity": "High", - "subcategory": "Host", - "text": "Storage networking is redundant", + "severity": "Medium", + "subcategory": "Compute", + "text": "Assess the requirement to backup AVD Session Host VMs", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "15d976c5-e267-49a1-8b00-62010bfa5188", - "id": "02.01.03", - "link": "https://learn.microsoft.com/azure-stack/hci/deploy/network-atc", - "services": [], + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Even for Personal Pools, usage of Availability Zones, when available, is recommended. Three possible in-region DR strategies are possible, it is recommended to select the best one based on cost, RTO/RPO, and if it is really necessary to save the entire VM OS disk: (1) create each session host in a specific zone (AZ) and then use Azure Site Recovery (ASR) to replicate to a different zone. (2) Use Azure Backup to backup and restore the specific session host in a different AZ. (3) Create a new session host in a different AZ and rely on FSLogix and/or OneDrive to make data and settings available on the new machine. All options require administrator intervention for DR and direct user assignment at Host Pool level, then must be planned and configured in advance.", + "guid": "5da58639-ca3a-4961-890b-29663c5e10d", + "id": "A01.06", + "link": "https://learn.microsoft.com/azure/site-recovery/azure-to-azure-how-to-enable-zone-to-zone-disaster-recovery", + "services": [ + "VM", + "Backup", + "ASR", + "AVD", + "Cost" + ], "severity": "Medium", - "subcategory": "Host", - "text": "Host networking configuration is managed by Network ATC and intents are healthy", + "subcategory": "Compute", + "text": "Prepare a local DR strategy for Personal Host Pool Session Hosts", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "676c53ad-b29a-4de1-9d03-d7d2674405b8", - "id": "02.01.04", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/network-hud-overview", - "services": [], + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "If custom images are used to deploy AVD Host Pool VMs, it is important to ensure those artifacts are available in all regions where AVD is deployed. Azure Compute Gallery service can be used to replicate images across all regions where a Host Pool is deployed, with redundant storage and in multiple copies. Please be aware that the Azure Compute Gallery service isn't a global resource. For disaster recovery scenarios, the best practice is to have at least two galleries, in different regions.", + "guid": "dd2e0d5d-771d-441e-9610-cc57b4a4a141", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/azure-compute-gallery", + "services": [ + "VM", + "Storage", + "ACR", + "ASR", + "AVD" + ], "severity": "Low", - "subcategory": "Host", - "text": "Network HUD has been configured", + "subcategory": "Dependencies", + "text": "Plan for Golden Image cross-region availability", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "8f6d58d9-6c1a-4ec1-b2d7-b2c6ba8f3949", - "id": "02.01.05", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/host-network-requirements", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "If users of the AVD infrastructure need on-premises resource access, high availability of network infrastructure required to connect is also critical and should be considered. Resiliency of authentication infrastructure needs to be assessed and evaluated. BCDR aspects for dependent applications and other resources need to be considered to ensure availability in the secondary DR location.", + "guid": "fd339489-8c12-488b-9c6a-57cfb644451e", + "id": "A02.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "VNet", - "Storage" + "AVD", + "ASR" ], "severity": "Medium", - "subcategory": "Host", - "text": "Storage NICs are assigned static IP addresses on separate subnets and VLANs", + "subcategory": "Dependencies", + "text": "Assess Infrastructure & Application dependencies ", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "824e53ec-953e-40c2-a6b8-52970b5b0f74", - "id": "02.01.06", - "link": "https://learn.microsoft.com/azure-stack/hci/plan/two-node-switched-converged", - "services": [], + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Not all data inside FSLogix user profiles may deserve protection from disaster. Additionally, if external storage is used, for example OneDrive or File Servers/Shares, what is remaining in the FSLogix profile is minimal and could be lost in some extreme circumstances. In other cases, data inside the profile can be rebuilt from other storages (for example Outlook Inbox in cached mode).", + "guid": "687ab077-adb5-49e5-a960-3334fdf8cc23", + "id": "A03.01", + "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt", + "services": [ + "AVD", + "Storage", + "ASR" + ], "severity": "Medium", - "subcategory": "Host", - "text": "For switchless designs, dual link full mesh connectivity has been implemented", + "subcategory": "Storage", + "text": "Assess which data need to be protected in the Profile and Office Containers", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "dbc85d0e-0ebd-4589-a789-0fa8ceb1d0f0", - "id": "02.01.07", - "link": "https://learn.microsoft.com/azure-stack/hci/concepts/physical-network-requirements#using-switchless", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Preventing data loss for critical user data is important, first step is to assess which data need to be saved and protected. If using OneDrive or other external storage, saving user Profile and/or Office Containers data maybe not necessary. Appropriate mechanism must be considered to provide protection for critical user data. Azure Backup service can be used to protect Profile and Office Containers data when stored on Azure Files Standard and Premium tiers. Azure NetApp Files Snapshots and Policies can be used for Azure NetApp Files (all tiers).", + "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", + "id": "A03.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "Storage" + "Storage", + "AzurePolicy", + "Backup", + "ASR", + "AVD" ], "severity": "Medium", - "subcategory": "Host", - "text": "If the cluster is made up of more than 3 nodes, a switched storage network has been implemented", + "subcategory": "Storage", + "text": "Build a backup protection strategy for Profile and Office Containers", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "603c6d71-59d2-419c-a312-8edc6e799c6a", - "id": "02.01.08", - "services": [ - "Storage" - ], - "severity": "High", - "subcategory": "Host", - "text": "RDMA is enabled on the Storage networking", - "waf": "Performance" - }, - { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "9e260eae-bca1-4827-a259-76ee63fda8d6", - "id": "02.01.09", - "link": "https://github.com/microsoft/SDN/blob/master/Diagnostics/Test-Rdma.ps1", - "services": [], - "severity": "Medium", - "subcategory": "Host", - "text": "Test-RDMA.ps1 has been run to validate the RDMA configuration", - "waf": "Performance" - }, - { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "description": "This ensures that Management traffic is not exposed to the VM traffic", - "guid": "abc85d0e-0ebd-4589-a777-0fa8ceb1d0f0", - "id": "02.01.10", - "link": "", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "In AVD, multiple replication mechanisms and strategies can be used for user data residing in FSLogix containers: [Profile Pattern #1]: Native Azure storage replication mechanisms, for example Azure Files Standard GRS replication, Azure NetApp Files Cross Region Replication. Use Zone Replicated Storage (ZRS) or Geo replicated storage (GRS) for Azure Files is recommended. LRS with local-only resiliency can be used if no zone/region protection is required. NOTE: Azure Files Share Standard is LRS/ZRS/GRS, but with 100TB large support enabled only LRS/ZRS are supported. [Profile Pattern #2]: FSLogix Cloud Cache is built in automatic mechanism to replicate containers between different (up to 4) storage accounts. Cloud Cache should be used only when:(1) User Profile or Office containers data availability required high-availability SLA is critical and need to be resilient to region failure. (2) Selected storage option is not able to satisfy BCDR requirements. For example, with Azure File Share Premium tier, or Azure File Share Standard with Large File Support enabled, GRS is not available. (3) When replication between disparate storage is required. [Profile Pattern #3]: Only set up geo disaster recovery for application data and not for user data/profile containers: store important application data in separate storages, like OneDrive or other external storage with its own built-in DR mechanism.", + "guid": "9f7547c1-746d-4c56-868a-714435bd09dd", + "id": "A03.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", "services": [ - "VM" + "AVD", + "Storage", + "ASR" ], "severity": "Medium", - "subcategory": "Host", - "text": "If a VMSwitch is shared for Compute and Management traffic, require that Management traffic is tagged with a VLAN ID", - "waf": "Security" + "subcategory": "Storage", + "text": "Assess Profile Container storage replication requirements and resiliency for BCDR purpose", + "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "description": "This ensures you have at least 3 NCs active at all times during NC upgrades.", - "guid": "eb36f5f4-0fa7-4a2c-85f3-1b1c7c7817c0", - "id": "02.02.01", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "For local disaster recovery, Azure Backup for Azure Files can be used. For cross-region geo disaster recovery: GRS for Azure Files is only available with standard SKU and no large share support, then not suitable in most customer scenarios. If geo-replication is required with Azure File Share Premium, replication with FSLogix Cloud Cache can be evaluated, or 'in-region' Availability Zone (AZ) only resiliency should be considered.", + "guid": "3d4f3537-c134-46dc-9602-7a71efe1bd05", + "id": "A03.04", + "link": "https://docs.microsoft.com/azure/backup/backup-afs", "services": [ - "VM" + "AVD", + "Storage", + "Backup", + "ASR" ], "severity": "Medium", - "subcategory": "SDN", - "text": "There are at least 3 Network Controller VMs deployed", + "subcategory": "Storage", + "text": "Review Azure Files disaster recovery strategy", "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "8bc78c85-6028-4a43-af2d-082a0a344909", - "id": "02.02.02", - "link": "https://learn.microsoft.com/windows-server/networking/sdn/manage/update-backup-restore", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "Zone Redundant Storage will maximize in-region resiliency for the user profile data. ZRS is supported for premium file shares through the 'FileStorage' storage account kind. ZRS is supported in standard general-purpose v2 storage accounts. Usage of zone redundant storage must be paired with zone redundant deployment of Session Hosts in each Host Pool. ", + "guid": "10d4e875-d502-4142-a795-f2b6eff34f88", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/storage/files/files-redundancy#zone-redundant-storage", "services": [ - "Backup" + "AVD", + "Storage", + "ASR" ], "severity": "High", - "subcategory": "SDN", - "text": "Backups of SDN infrastructure are configured and tested", - "waf": "Operations" + "subcategory": "Storage", + "text": "Use Zone Redundant Storage (ZRS) for Azure Files to maximize resiliency", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Stack HCI Review", - "guid": "51eaa4b6-b9a7-43e1-a7dc-634d3107bc6d", - "id": "03.01.01", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Virtual Desktop Review", + "description": "For local disaster recovery, Azure NetApp Files (ANF) native backup is available. ANF is essentially locally redundant, then for cross-region geo disaster recovery it is necessary to use an additional mechanism that is Cross-Region Replication (CRR) https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering. Currently, ANF does not provide replication nor redundancy across different Availability Zones (AZ), only the possibility to select in which single AZ to place the ANF volume: https://learn.microsoft.com/azure/azure-netapp-files/manage-availability-zone-volume-placement.", + "guid": "23429db7-2281-4376-85cc-57b4a4b18142", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering", "services": [ - "Monitor" + "Storage", + "Backup", + "ACR", + "ASR", + "AVD" ], "severity": "Medium", - "subcategory": "Cluster", - "text": "SCOM Managed Instance has been considered for more complex monitoring and alerting scenarios", - "waf": "Operations" + "subcategory": "Storage", + "text": "Review Azure NetApp Files disaster recovery strategy", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Stack HCI Review", - "guid": "831f5aca-99ef-41e7-8263-9509f5093b43", - "id": "03.01.02", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/setup-hci-system-alerts", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Applications can be preinstalled in the golden image/s, can be attached using MSIX & AppAttach feature or distributed to the session hosts after host pool deployment using traditional software distribution methods.", + "guid": "86ba2802-1459-4014-95d3-8e5309ccbd97", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", "services": [ - "Monitor" + "AVD" ], "severity": "High", - "subcategory": "Cluster", - "text": "Alerts have been configured for the cluster, either using Azure Monitor, SCOM, or a third-party solution", - "waf": "Operations" - }, - { - "category": "Management and Monitoring", - "checklist": "Azure Stack HCI Review", - "guid": "f95d0e7e-9f61-476d-bf65-59f2454d1d39", - "id": "03.01.03", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/monitor-hci-single?tabs=22h2-and-later", - "services": [ - "Monitor" - ], - "severity": "Medium", - "subcategory": "Cluster", - "text": "Insights has been enabled at the cluster level and all nodes are reporting data", + "subcategory": "Golden Images", + "text": "Determine how applications will be deployed in AVD Host Pools", "waf": "Operations" }, { - "category": "Management and Monitoring", - "checklist": "Azure Stack HCI Review", - "guid": "f4250fcb-ff53-40c9-b304-3560464fd90c", - "id": "03.01.04", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/monitor-hci-single?tabs=22h2-and-later", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Multiple golden images can be required to support different OS versions and/or settings, different groups of applications that must be separated and cannot be included in a single image.", + "guid": "9266bcca-274f-4aa1-abf3-9d95d44c7c89", + "id": "B01.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", "services": [ - "Monitor" + "AVD" ], "severity": "Medium", - "subcategory": "Cluster", - "text": "Azure Monitoring Agent has been deployed to hosts and an appropriate Data Collection Rule has been configured", + "subcategory": "Golden Images", + "text": "Estimate the number of golden images that will be required", "waf": "Operations" }, { - "category": "Management and Monitoring", - "checklist": "Azure Stack HCI Review", - "guid": "6143af1d-0d1a-4163-b1c9-662f7459bb98", - "id": "03.02.01", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Determine which Guest OS will be used to deploy each Host Pool: Windows 10 vs. Windows Server, Marketplace vs. Custom images", + "guid": "19ca1f6d-5315-4ae5-84ba-34d4585e2213", + "id": "B01.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#operating-systems-and-licenses", "services": [ - "Monitor" + "AVD" ], "severity": "Medium", - "subcategory": "Hardware", - "text": "Relevant hardware monitoring has been configured", - "waf": "Operations" + "subcategory": "Golden Images", + "text": "Determine which OS image/s you will use for Host Pool deployment", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Stack HCI Review", - "guid": "9cbdf225-549a-41cf-9c97-794766a6f2b0", - "id": "03.02.02", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/health-service-overview", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure VM custom images can be created and stored in different ways: in an Azure Compute Gallery, as a managed image object or as a managed disk in the storage. The recommended way is to use Azure Compute Gallery.", + "guid": "5a2adb2c-3e23-426b-b225-ca44e1696fdd", + "id": "B01.04", + "link": "https://learn.microsoft.com/azure/virtual-machines/shared-image-galleries", "services": [ - "Monitor" + "AVD", + "VM", + "Storage" ], - "severity": "Medium", - "subcategory": "Hardware", - "text": "Relevant hardware alerting has been configured", - "waf": "Operations" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Select the proper store for custom images", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "c0da5bbd-0f0d-4a26-98ec-38c9cc42b323", - "id": "04.01.01", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "If custom images will be used, plan for an automated build process. If no pre-existing software factory exists, consider using Custom Image Templates and/or Azure Image Builder to automate the build process.", + "guid": "9bd7bb01-2f7b-495e-86e1-54e2aa359282", + "id": "B01.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/create-custom-image-templates", "services": [ - "VM" + "AVD" ], "severity": "Low", - "subcategory": "VM Management - Resource Bridge", - "text": "The Azure CLI has been installed on every node to enable RB management from WAC", + "subcategory": "Golden Images", + "text": "Design your build process for custom images", "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "a8ecf23c-c048-4fa9-b87b-51ebfb409863", - "id": "04.01.02", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "There are some known best practices and recommendations for the golden image customization, be sure to check the referenced article.", + "guid": "deace4cb-1dec-44c6-90c3-fc14eebb36a3", + "id": "B01.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", "services": [ - "VM" + "AVD" ], - "severity": "Low", - "subcategory": "VM Management - Resource Bridge", - "text": "DHCP is available in the cluster to support Guest Configuration at VM deployment from Azure", + "severity": "Medium", + "subcategory": "Golden Images", + "text": "If custom image will be used, check recommended best practices for AVD on how to build custom image", "waf": "Operations" }, { - "category": "Backup and Disaster Recovery", - "checklist": "Azure Stack HCI Review", - "guid": "074541e3-fe08-458a-8062-32d13dcc10c6", - "id": "05.01.01", - "link": "https://learn.microsoft.com/azure/backup/back-up-azure-stack-hyperconverged-infrastructure-virtual-machines", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "FSLogix stack installed in AVD session hosts does not provide auto-update capability. For this reason, it is recommended to download the latest version of FSLogix and include in the golden image update process.", + "guid": "ed5c9027-dd1a-4343-86ca-52b199223186", + "id": "B01.07", + "link": "https://learn.microsoft.com/fslogix/how-to-install-fslogix", "services": [ - "VM", - "Backup", - "ASR" + "AVD" ], "severity": "High", - "subcategory": "VM", - "text": "Backups of HCI VMs have been configured using MABS or a third-party solution", - "waf": "Operations" + "subcategory": "Golden Images", + "text": "Include the latest version of FSLogix in the golden image update process", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "48f7ae57-1035-4101-8a38-fbe163d03e8a", - "id": "06.01.01", - "services": [], - "severity": "High", - "subcategory": "Cluster Configuration", - "text": "Cluster configuration or a configuration script has been documented and maintained", - "waf": "Operations" - }, - { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "f2a6a19a-ffe6-444d-badb-cb336c8e7b50", - "id": "06.01.02", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/witness", - "services": [], - "severity": "High", - "subcategory": "Cluster Configuration", - "text": "A cluster witness has been configured for clusters with less than 5 nodes", - "waf": "Reliability" + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "This tool-set has been created to automatically apply setting referenced in white paper 'Optimizing Windows 10, version 2004 for a Virtual Desktop Infrastructure (VDI) role': https://docs.microsoft.com/windows-server/remote/remote-desktop-services/rds-vdi-recommendations-2004. Usage of the tool and/or optimizations mentioned in the white-paper should be considered. ", + "guid": "829e3fec-2183-4687-a017-7a2b5945bda4", + "id": "B01.08", + "link": "https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool", + "services": [ + "AVD", + "RBAC" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Evaluate the usage of Virtual-Desktop-Optimization-Tool", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "a47339fe-62c5-44a0-bb83-3d46ef16292f", - "id": "06.01.03", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/update-cluster", - "services": [], - "severity": "Medium", - "subcategory": "Cluster Configuration", - "text": "Cluster-Aware Updating has been configured for Windows and hardware updates (if available)", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "If OneDrive is used and included in a golden image, be sure to follow the configuration procedure reported in the companion article in the 'More Info' section. Not in scope in this AVD checklist, but OneDrive optimizations like 'Known Folder Redirection' and 'Files On-Demand' should be evaluated used to reduce the space used in FSLogix profiles and provide a better user experience. OneDrive today is not supported for Remote Apps.", + "guid": "e3d3e084-4276-4d4b-bc01-5bcf219e4a1e", + "id": "B01.09", + "link": "https://learn.microsoft.com/azure/virtual-desktop/install-office-on-wvd-master-image#install-onedrive-in-per-machine-mode", + "services": [ + "AVD", + "Storage" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Determine if Microsoft OneDrive will be part of AVD deployment", "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "7f1d6fe8-3079-44ea-8ea6-14494d1aa470", - "id": "06.01.04", - "link": "https://learn.microsoft.com/azure-stack/hci/deploy/validate", - "services": [], - "severity": "High", - "subcategory": "Cluster Configuration", - "text": "Cluster validation has been run against the configured cluster", - "waf": "Reliability" - }, - { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "81693af0-5638-4aa2-a153-1d6189df30a7", - "id": "06.01.05", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/azure-benefits", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Be sure to review the requirements and configuration procedure contained in the companion article in the 'More Info' column. Since Teams automatic updates will be disabled, it is recommended to check and include Teams latest version in the golden image update process.", + "guid": "b5887953-5d22-4788-9d30-b66c67be5951", + "id": "B01.10", + "link": "https://learn.microsoft.com/azure/virtual-desktop/teams-on-AVD", "services": [ - "VM" + "AVD" ], - "severity": "Medium", - "subcategory": "Cluster Configuration", - "text": "Azure Benefits has been enabled at the cluster and VM levels", - "waf": "Cost" + "severity": "Low", + "subcategory": "Golden Images", + "text": "Determine if Microsoft Teams will be part of AVD deployment", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "8c967ee8-8170-4537-a28d-33431cd3632a", - "id": "06.01.06", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/use-environment-checker", - "services": [], - "severity": "Medium", - "subcategory": "Cluster Configuration", - "text": "The Environment Checker module has been run to validate the environment", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD can support users with different language and localization requirements in the same host pool. This can be done customizing golden images to ensure users can select whichever language they need. The procedure to configure additional language packs in Windows 11 is documented in the reference article.", + "guid": "7c336f3b-822a-498e-8cd1-667d1150df4a", + "id": "B01.11", + "link": "https://learn.microsoft.com/azure/virtual-desktop/windows-11-language-packs", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Assess the requirement to support multiple languages", "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "43ffbfab-766e-4950-a102-78b479136e4d", - "id": "06.02.01", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/azure-benefits", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "It is highly recommended to use separate storage accounts/shares to store MSIX packages. If necessary, storage can scale out independently and not being impacted by profile I/O activities. Azure offers multiple storage options that can be used for MISX app attach. We recommend using Azure Files or Azure NetApp Files as those options offer the best value between cost and management overhead. ", + "guid": "90083845-c587-4cb3-a1ec-16a1d076ef9f", + "id": "B02.01", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", "services": [ - "AzurePolicy" + "AVD", + "Storage", + "Cost" ], "severity": "Medium", - "subcategory": "Cluster Configuration", - "text": "Group Policy inheritance on the HCI cluster and node Active Directory organizational unit has been blocked or applied policies have been evaluated for compatibility issues (usually WinRM and PowerShell execution policy)", - "waf": "Operations" + "subcategory": "MSIX & AppAttach", + "text": "Do not use the same storage account/share as FSLogix profiles", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "e6a3f3a7-4a7d-49e2-985a-6e39dd284027", - "id": "06.02.02", - "services": [], + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "In the referenced article, we reported few but important performance considerations for MSIX usage in AVD context, be sure to carefully review.", + "guid": "241addce-5793-477b-adb3-751ab2ac1fad", + "id": "B02.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "services": [ + "AVD" + ], "severity": "Medium", - "subcategory": "Cluster Configuration", - "text": "WAC is on the latest release and configured to automatically upgrade extensions", - "waf": "Reliability" + "subcategory": "MSIX & AppAttach", + "text": "Review performance considerations for MSIX", + "waf": "Performance" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "d1caa31f-cc26-42b2-b92f-2b667c0e6020", - "id": "07.01.01", - "link": "https://learn.microsoft.com/azure/architecture/hybrid/azure-stack-hci-dr", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "MSIX app attach requires read-only permissions to access the file share. If you're storing your MSIX applications in Azure Files, then for your session hosts, you'll need to assign all session host VMs both storage account role-based access control (RBAC) and file share New Technology File System (NTFS) permissions on the share.", + "guid": "66e15d4d-5a2a-4db2-a3e2-326bf225ca41", + "id": "B02.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", "services": [ - "Entra" + "AVD", + "VM", + "Storage", + "RBAC" ], "severity": "Medium", - "subcategory": "Stretch Clustering", - "text": "There is sub 5ms latency between each site if synchronous replication is being configured AAD", - "waf": "Performance" + "subcategory": "MSIX & AppAttach", + "text": "Check proper session host permissions for MSIX share", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "3277558e-3155-4088-b49a-78594cb4ce1a", - "id": "07.01.02", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "3rd-party software vendor must provide a MSIX package, it is not recommended for customer to attempt the conversion procedure without proper support from the application owner.", + "guid": "bd362caa-ab79-4b19-adab-81932c9fc9d1", + "id": "B02.04", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", "services": [ - "VNet", - "Storage" + "AVD" ], - "severity": "High", - "subcategory": "Stretch Clustering", - "text": "Management, Replication and Storage networks excluded from stretched VLANs configurations, are routed, and in different subnets", - "waf": "Reliability" + "severity": "Low", + "subcategory": "MSIX & AppAttach", + "text": "MSIX packages for 3rd-party applications", + "waf": "Cost" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "baed6066-8531-44ba-bd94-38cbabbf4099", - "id": "07.02.01", - "services": [], - "severity": "High", - "subcategory": "Stretch Clustering", - "text": "There is a plan detailed for site failure and recovery", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "MSIX app attach doesn't support auto-update for MSIX applications, so they should be disabled.", + "guid": "bb88037f-5e6b-4fbb-aed5-03547cc447e8", + "id": "B02.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "MSIX & AppAttach", + "text": "Disable auto-update for MSIX packages", "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure Stack HCI Review", - "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b4", - "id": "07.02.02", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "In order to leverage MSIX & App Attach, guest OS image for AVD Host pool must be Windows 10/11 Enterprise or Windows 10/11 Enterprise Multi-session, version 2004 or later.", + "guid": "26128a71-f0f1-4cac-9d9e-f1d5e832e42e", + "id": "B02.06", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", "services": [ - "ACR" + "AVD" ], "severity": "Medium", - "subcategory": "Stretch Clustering", - "text": "Separate vLANs and networks are used for each replication network across both sites", + "subcategory": "MSIX & AppAttach", + "text": "Review operating systems support", "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b5", - "id": "07.02.03", - "link": "https://learn.microsoft.com/azure/architecture/hybrid/azure-stack-hci-dr#cost-optimization", + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "Once selected the VM SKU that will be used for Host Pool deployment, it is recommended to use Gen2 type of the SKU for higher security and improved capabilities.", + "guid": "e4633254-3185-40a1-b120-bd563a1c8e9d", + "id": "B03.01", + "link": "https://docs.microsoft.com/azure/virtual-machines/generation-2", "services": [ - "Storage" + "AVD", + "VM" ], - "severity": "High", - "subcategory": "Stretch Clustering", - "text": "Use either a cloud witness or a file share witness in a third site for cluster quorum for clusters with less than 5 nodes", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Session Host", + "text": "Evaluate the usage of Gen2 VM for Host Pool deployment", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b6", - "id": "07.02.04", - "link": "https://learn.microsoft.com/azure/architecture/hybrid/azure-stack-hci-dr#cost-optimization", - "services": [], - "severity": "High", - "subcategory": "Stretch Clustering", - "text": "When using data deduplication, only enable it on the primary/source volumes", - "waf": "Reliability" + "category": "Compute", + "checklist": "Azure Virtual Desktop Review", + "description": "MMR redirects the media content from Session Host to your local machine for faster processing and rendering. It only works when you play media content on Microsoft Edge or Google Chrome. See linked URL for more details.", + "guid": "adecb27f-dc40-40f5-aca2-0090f633b1c9", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/multimedia-redirection", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Session Host", + "text": "Consider using MMR (MultiMedia Redirection) to get better video performance on browser", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure Stack HCI Review", - "guid": "ac527887-f6f4-40a3-b883-e04d704f013b", - "id": "07.02.04", - "link": "https://learn.microsoft.com/windows-server/storage/storage-replica/stretch-cluster-replication-using-shared-storage#provision-operating-system-features-roles-storage-and-network", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "A host pool is a collection of Azure virtual machines that register to Azure Virtual Desktop as session hosts. A host pool can be one of two types: Personal and Pooled. Which type to use, and how many, is a key design decision that must be documented and validated. See companion article in 'More Info' column for more details.", + "guid": "8468c55a-775c-46ee-a5b8-6ad8844ce3b2", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology#host-pools", "services": [ - "Storage" + "AVD", + "VM" ], "severity": "High", - "subcategory": "Stretch Clustering", - "text": "Storage backing log volumes must be faster (ideally) or at least as fast as capacity storage", - "waf": "Reliability" + "subcategory": "Capacity Planning", + "text": "Determine the Host Pool type to use", + "waf": "Cost" }, { - "category": "Backup and Disaster Recovery", - "checklist": "Azure Stack HCI Review", - "guid": "8ea49f70-1038-4283-b0c4-230165d3eabc", - "id": "08.01.01", - "link": "https://learn.microsoft.com/azure-stack/hci/manage/azure-site-recovery", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Use your design criteria to determine the number of Host Pools to deploy. This will be based on factors such as different OS images, multi-region support, guest VM hardware differences (such as GPU support or no), different user expectations and uptime requirements (examples might be 'Executives', 'Office Workers', 'Developers', etc.), and Host Pool RDP settings (such as drive redirection support). These will determine the number of host pools as well as how many hosts will be in each pool.", + "guid": "4e98495f-d3c0-4af2-aa59-a793395a32a7", + "id": "C01.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#host-pools", "services": [ - "Backup", - "ASR" + "AVD", + "VM" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Azure Site Recovery has been considered for DR purposes", - "waf": "Operations" - }, - { - "category": "Security", - "checklist": "Azure Stack HCI Review", - "guid": "03e65fdc-2628-4a1a-ba2e-a5174340ba52", - "id": "09.01.01", - "link": "https://learn.microsoft.com/windows/security/operating-system-security/data-protection/bitlocker/protecting-cluster-shared-volumes-and-storage-area-networks-with-bitlocker", - "services": [], - "severity": "Medium", - "subcategory": "Host", - "text": "BitLocker has been enabled on CSVs for volume encryption, where appropriate", - "waf": "Security" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Estimate the number of different Host Pools to deploy ", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Stack HCI Review", - "guid": "9645d2e6-ba28-453c-b6d5-d9ef29fc34be", - "id": "09.01.02", - "link": "https://learn.microsoft.com/windows-server/storage/file-server/smb-security", - "services": [], - "severity": "Medium", - "subcategory": "Host", - "text": "SMB encryption has been enabled, where appropriate", - "waf": "Security" + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Confirm that the difference between automatic and direct assignment is well understood and the selected option is appropriate for the scenario in question. Automatic is the default setting.", + "guid": "b38b875b-a1cf-4204-a901-3a5d3ce474db", + "id": "C01.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "For Personal Host Pool type, select the proper assignment type", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Stack HCI Review", - "guid": "8f03437a-5068-4486-9a78-0402ce771298", - "id": "09.01.03", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-on-windows-server", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Check which one to use and available options, autoscale ignores existing load-balancing algorithms.", + "guid": "cbd8682a-6abc-4a2a-9fda-1dbf3dc95d48", + "id": "C01.04", + "link": "https://docs.microsoft.com/azure/virtual-desktop/host-pool-load-balancing", "services": [ - "Defender" + "AVD" ], - "severity": "Medium", - "subcategory": "Host", - "text": "Microsoft Defender Antivirus has been enabled on all nodes", - "waf": "Security" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "For Pooled Host Pool type, select the best load balancing method", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Stack HCI Review", - "guid": "dba6b211-fc02-43b3-b7c8-f163c188332e", - "id": "09.01.04", - "link": "https://learn.microsoft.com/windows/security/identity-protection/credential-guard/credential-guard-manage", - "services": [], + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "The number of cores increase, the system's synchronization overhead also increases. Especially for multiple user's sign-in simultaneously. Make sure not to use a VM that is too large for the session host", + "guid": "b3724959-4943-4577-a3a9-e10ff6345f24", + "id": "C01.05", + "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "services": [ + "AVD", + "VM" + ], "severity": "Medium", - "subcategory": "Host", - "text": "Credential Guard has been configured, where appropriate", - "waf": "Security" + "subcategory": "Capacity Planning", + "text": "For Pooled Host Pool type, VMs shouldn't have more than 32 cores", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", - "guid": "976f32a7-30d1-6caa-c2a0-207fdc26571b", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD does not support assigning both the RemoteApp and Desktop Application Group (DAG) in a single host pool to the same set of users. Doing so will cause a single user to have two user sessions in a single host pool. Users aren't supposed to have two active sessions at the same time in the same host pool using the same profile.", + "guid": "b384b7ed-1cdd-457e-a2cd-c8d4d55bc144", + "id": "C01.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#application-groups", "services": [ - "Backup", - "AVS", + "AVD", "Storage" ], - "severity": "Medium", - "subcategory": "Backup", - "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", - "waf": "Reliability" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Do not use the same Host Pool to offer both full desktops (DAG) and Remote Apps to the same set of users", + "waf": "Security" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Microsoft backup service", - "guid": "fc8af7a1-c724-e255-c18d-4ca22a6f27f0", - "id": "A02.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "There is a limit of 500 Application Groups that can be created in AVD for each Microsoft Entra ID (former Azure AD) tenant. The limit can be increased (see the companion link for details) but it is not recommended.", + "guid": "971cc4a4-b1f7-4c12-90e0-1ad96808f00c", + "id": "C01.07", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-virtual-desktop-service-limits", "services": [ - "Backup", - "AVS" + "AVD", + "ACR", + "Entra" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Use MABS as your backup solution", + "subcategory": "Capacity Planning", + "text": "Estimate the number of Application Groups required across all Host Pools in the Microsoft Entra ID tenant", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Best practice - this is Backup, not disaster recovery", - "guid": "be28860f-3d29-a79a-1a0e-36f1b23b36ae", - "id": "A02.02", - "link": "Best practice to deploy backup in the same region as your AVS deployment", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Applications are grouped under Application Groups as containers for publishing and assigning permissions: we recommend that you do not publish more than 50 applications per application group.", + "guid": "fa9f2895-473d-439b-ab8e-5a5cf92c7f32", + "id": "C01.08", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", "services": [ - "Backup", - "AVS", - "ASR" + "AVD" ], - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Estimate the number of Applications for each Application Group", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Best practice - in case AVS is unavailable", - "guid": "4d2f79a5-4ccf-0dfc-557c-49619b99a540", - "id": "A02.03", - "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "FSLogix is not required for Personal Host Pools since each VM is statically assigned to a single user, then no immediate needs for a roaming profile solution. In some usage scenarios FSLogix can help. For example, a VM can be re-assigned, or user moved to another desktop, or roaming profile can be used to save user profile in a different location for DR purposes.", + "guid": "38b19ab6-0693-4992-9394-5590883916ec", + "id": "C01.09", + "link": "https://learn.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type?tabs=azure#reassign-a-personal-desktop", "services": [ - "AVS" + "AVD", + "VM", + "Storage" ], - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Evaluate the usage of FSLogix for Personal Host Pools", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", - "guid": "ff431c40-962c-5182-d536-0c2f0c4ce9e0", - "id": "A02.04", - "link": "Will Disaster Recovery Site Recovery, HCX Disaster Recovery, SRM or back tools be used?", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Use the link provided to set a starting point for SKU decision, then validate using a performance test. Ensure a minimum of four cores for Production is selected per Session Host (multi-session)", + "guid": "e1112dbd-7ba0-412e-9b94-ef6e047d2ea2", + "id": "C01.10", + "link": "https://docs.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", "services": [ - "AVS" + "AVD", + "VM" ], - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Escalation process with Microsoft in the event of a regional DR", - "waf": "Reliability" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Run workload performance test to determine the best Azure VM SKU and size to use", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Compare SRM with HCX", - "guid": "f379436d-3051-daa0-01fb-dc4e0e04d677", - "id": "A03.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/disaster-recovery-using-vmware-site-recovery-manager", - "services": [ - "AVS", - "ASR" - ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", - "waf": "Reliability" - }, - { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Recovery into Azure instead of Vmware solution", - "guid": "367f71d8-3cf6-51a0-91a5-3db3d570cc19", - "id": "A03.02", - "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "It is critical to check AVD capacity and limits reported in the referenced article. Additional limits and thresholds apply for network, compute, storage and service management. ", + "guid": "992b1cd6-d2f5-44b2-a769-e3a691e8838a", + "id": "C01.11", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", "services": [ - "AVS", - "ASR" + "AVD", + "Storage" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Verify AVD scalability limits for the environment", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Avoid manual tasks as much as possible", - "guid": "ee02ada0-1887-bb3a-b84c-423f45a09ef9", - "id": "A03.03", - "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Host Pools with GPU require special configuration, please be sure to review the referenced article.", + "guid": "c936667e-13c0-4056-94b1-e945a459837e", + "id": "C01.12", + "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-vm-gpu", "services": [ - "AVS", - "ASR" + "AVD" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Automated recovery plans with either of the Disaster solutions,", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Determine if Session Hosts will require GPU", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Any other datacenter in the same region", - "guid": "0c2b74e5-9c28-780d-1df3-12d3de4aaa76", - "id": "A03.04", - "link": "https://docs.microsoft.com/azure/azure-vmware/connect-multiple-private-clouds-same-region", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Whenever is possible, it is recommended to leverage VM SKUs with Accelerated Networking feature. This feature does require specific VM SKU/size and OS versions, please see the list and requirement in the companion article.", + "guid": "b47a393a-0803-4272-a479-8b1578b219a4", + "id": "C01.13", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", "services": [ - "AVS", - "ASR" + "AVD", + "VM" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Configure a secondary disaster recovery environment", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Use Azure VM SKUs able to leverage Accelerated Networking", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", - "guid": "c2a34ec4-2933-4e6c-dc36-e20e67abbe3f", - "id": "A03.05", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "For proper planning and deployment, it is important to assess the maximum number of concurrent and total users for each Host Pool. Additionally, users from different regions may require different Host Pools to ensure the best user experience.", + "guid": "bb91a33d-90ca-4e2c-a881-3706f7c0cb9f", + "id": "C02.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", "services": [ - "AVS", - "ASR" + "AVD" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Assign IP ranges unique to each region", - "waf": "Reliability" + "subcategory": "Clients & Users", + "text": "Assess how many users will connect to AVD and from which regions", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "ExpressRoute Global Reach can be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or routing must be done through network virtual appliances?", - "guid": "b44fb6ec-bfc1-3a8e-dba2-ca97f0991d2c", - "id": "A03.06", - "link": "This depends if you have multiple AVS Private Clouds. If so and they are in the same region then use AVS Interconnect. If they are in separate regions then use ExpressRoute Global Reach.", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "The dependencies on resources external to the AVD pool should be assessed and reviewed, for example Active Directory, external file shares or other storage, on-premises services and resources, network infrastructure components like VPN and or ExpressRoute, external services and 3rd-party components. For all these resources, latency from the AVD Host Pool needs to be evaluated and connectivity considered. Additionally, BCDR considerations need to be applied to these dependencies as well.", + "guid": "6abca2a4-fda1-4dbf-9dc9-5d48c7c791dc", + "id": "C02.02", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?toc=%2Fazure%2Fvirtual-desktop%2Ftoc.json&bc=%2Fazure%2Fvirtual-desktop%2Fbreadcrumb%2Ftoc.json", "services": [ - "NVA", - "AVS", "ExpressRoute", - "ASR" + "AVD", + "VPN", + "Storage" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Global Reach between DR regions", - "waf": "Reliability" + "subcategory": "Clients & Users", + "text": "Assess external dependencies for each Host Pool", + "waf": "Performance" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "An ExR Global Reach connection will be established to the ExR circuit, no other connections", - "guid": "a2c12df2-07fa-3edd-2cec-fda0b55fb952", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD offers a variety of client types (fat, thin, web) to connect over different platforms (Windows, MacOS, iOS, Android). Review limitations of each client and compare multiple options when possible.", + "guid": "a1f6d565-99e5-458b-a37d-4985e1112dbd", + "id": "C02.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/users/connect-windows", "services": [ - "AVS", - "VWAN" + "AVD" ], - "severity": "Medium", - "subcategory": "Direct (no vWAN, no H&S)", - "text": "Global Reach to ExR circuit - no Azure resources", + "severity": "Low", + "subcategory": "Clients & Users", + "text": "Review user client OS used and AVD client type", "waf": "Performance" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use ExR to connect on-premises (other) location to Azure", - "guid": "f62ce162-ba5a-429d-674e-fafa1af5f706", - "id": "B02.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Depending on the user locations, and AVD region deployment, users may have a non-optimal experience, hence is important to test as soon as possible in a small PoC environment. Run the 'Azure Virtual Desktop Experience Estimator' tool to select the best Azure region to deploy Host Pools. Beyond 150ms latency, user experience may be not optimal.", + "guid": "d2f54b29-769e-43a6-a1e8-838ac936667e", + "id": "C02.04", + "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", "services": [ - "AVS", - "ExpressRoute" + "AVD" ], - "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Connect to Azure using ExR", + "severity": "High", + "subcategory": "Clients & Users", + "text": "Run a PoC to validate end-to-end user experience and impact of network latency", "waf": "Performance" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use the migration assesment tool and timeline to determine bandwidth required", - "guid": "cf01c73b-1247-0a7a-740c-e1ea29bda340", - "id": "B02.02", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-introduction", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "RDP settings can currently only be configured at the host pool level, not per user/group. If different settings are required for different set of users, it is recommended to create multiple Host Pools.", + "guid": "3b365a5c-7acb-4e48-abe5-4cd79f2e8776", + "id": "C02.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/customize-rdp-properties", "services": [ - "AVS", - "ExpressRoute" + "AVD" ], - "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Bandwidth sizing", - "waf": "Performance" + "severity": "Low", + "subcategory": "Clients & Users", + "text": "Assess and document RDP settings for all user groups", + "waf": "Security" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "What traffic is routed through a firewall, what goes directly into Azure", - "guid": "aab216ee-8941-315e-eada-c7e1f2243bd1", - "id": "B02.03", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD is a non-regional service, Host Pools can be created in any region, automatic redirection from closest front-end will happen automatically.", + "guid": "42e52f47-21d9-428c-8b1b-d521e44a29a9", + "id": "C03.01", + "link": "https://azure.microsoft.com/global-infrastructure/services/?products=virtual-desktop", "services": [ - "AVS", - "ExpressRoute" + "AVD" ], - "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Traffic routing ", + "severity": "High", + "subcategory": "General", + "text": "Determine in which Azure regions AVD Host Pools will be deployed.", "waf": "Performance" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "AVS to ExR circuit, no traffic inspection", - "guid": "1f956e45-f62d-5c95-3a95-3bab718907f8", - "id": "B02.04", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD must store metadata to support the service; this is stored in the specified geography. However, this is independent of the regions where Host Pools are located.", + "guid": "bad37ead-53cc-47ce-8d7a-aab3571449ab", + "id": "C03.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/data-locations", "services": [ - "AVS", - "ExpressRoute" + "AVD" ], "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Global Reach ", - "waf": "Performance" + "subcategory": "General", + "text": "Determine metadata location for AVD service", + "waf": "Reliability" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Name of the vNet and a unique address space /24 minimum", - "guid": "91f7a87b-21ac-d712-959c-8df2ba034253", - "id": "B03.01", - "link": "https://learn.microsoft.com/azure/virtual-network/quick-create-portal", + "category": "Foundation", + "checklist": "Azure Virtual Desktop Review", + "description": "Check for specific VM SKUs, especially if you need GPU or high-specs SKUs, and eventually Azure NetApp Files if used.", + "guid": "8053d89e-89dc-47b3-9be2-a1a27f7a9e91", + "id": "C03.03", + "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "services": [ - "VNet", - "AVS" + "AVD", + "VM", + "Storage" ], - "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "VNet name & address space", - "waf": "Performance" - }, - { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Subnet must be called GatewaySubnet", - "guid": "58a027e2-f37f-b540-45d5-e44843aba26b", - "id": "B03.02", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", - "services": [ - "VNet", - "AVS", - "ExpressRoute", - "VPN" - ], - "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "Gateway subnet", - "waf": "Performance" + "severity": "Low", + "subcategory": "General", + "text": "Check Azure quotas and availability for specific VM sizes and types in the selected regions", + "waf": "Reliability" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create a VPN gateway on the hub Gateway subnet", - "guid": "d4806549-0913-3e79-b580-ac2d3706e65a", - "id": "B03.03", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "AD DCs in Azure are recommended (at least two in different AZ) to reduce latency for users logging into AVD session hosts, and eventually for Azure NetApp Files and AD integration. A DC need to be able to talk to DCs for ALL child domains. As alternative, on-premise connectivity must be used to reach AD DCs.", + "guid": "c14aea7e-65e8-4d9a-9aec-218e6436b073", + "id": "D01.01", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "services": [ + "Storage", + "AVD", "VNet", - "AVS", - "VPN", - "ExpressRoute" + "Entra" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "VPN Gateway", - "waf": "Performance" + "subcategory": "Active Directory", + "text": "Create at least two Active Directory Domain Controllers (DCs) in Azure VNet environment close to AVD Host Pool", + "waf": "Reliability" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create an ExR Gateway in the hub Gateway subnet.", - "guid": "864d7a8b-7016-c769-a717-61af6bfb73d2", - "id": "B03.04", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "Recommended to create a separate OU per Host Pool under a separate OU hierarchy. These OUs will contain machine accounts of AVD Session Hosts. ", + "guid": "6db55f57-9603-4334-adf9-cc23418db612", + "id": "D01.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", "services": [ - "VNet", - "AVS", - "ExpressRoute", - "VPN" + "AVD", + "Entra" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "ExR Gateway", - "waf": "Performance" + "subcategory": "Active Directory", + "text": "Create a specific OU in Active Directory for each Host Pool", + "waf": "Operations" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "How will Internet traffic be routes, Az Firewall, NVA, Secure Hub, On-Premises firewall?", - "guid": "cc2e11b9-7911-7da1-458c-d7fcef794aad", - "id": "B04.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/enable-public-internet-access", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "Carefully review, and potentially block/filter inheritance of GPOs to the OUs containing AVD Host Pools. ", + "guid": "7126504b-b47a-4393-a080-327294798b15", + "id": "D01.03", + "link": "https://docs.microsoft.com/previous-versions/windows/desktop/Policy/group-policy-hierarchy", "services": [ - "NVA", - "AVS" + "AVD", + "Entra" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Egress point", - "waf": "Performance" + "subcategory": "Active Directory", + "text": "Review Domain GPOs that will be applied to OU and impacting Host Pool Session Hosts functionalities", + "waf": "Operations" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Allow remote connectivity to AVS via the portal, specifically to vCenter, NSX-T and HCX", - "guid": "71e68ce3-982e-5e56-0191-01100ad0e66f", - "id": "B05.01", - "link": "https://learn.microsoft.com/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "If Active Directory Domain GPOs are used, it is recommended to configure FSLogix using the built-in provided GPO ADMX template referenced in the companion article in the 'More Info' column", + "guid": "2226a8e3-50a4-4ac3-8bd6-ee150553051f", + "id": "D01.04", + "link": "https://learn.microsoft.com/fslogix/how-to-use-group-policy-templates", "services": [ - "AVS", - "Bastion" + "AVD", + "Entra" ], "severity": "Medium", - "subcategory": "Jumpbox & Bastion", - "text": "Remote connectivity to AVS", - "waf": "Performance" + "subcategory": "Active Directory", + "text": "Configure FSLogix settings using the built-in provided GPO ADMX template", + "waf": "Operations" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Name the jumpbox and identify the subnet where it will be hosted", - "guid": "6f8e93a2-44b1-bb1d-28a1-4d5b3c2ea857", - "id": "B05.02", - "link": "https://learn.microsoft.com/azure/bastion/tutorial-create-host-portal", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "It is recommended to have a specific dedicated account with minimal permissions, and without the default 10 joins limitation. Review the companion article for more details.", + "guid": "347dc560-28a7-41ff-b1cd-15dd2f0d5e77", + "id": "D01.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#session-hosts", "services": [ - "VNet", - "AVS", - "Bastion" + "AVD", + "VM", + "Entra" ], "severity": "Medium", - "subcategory": "Jumpbox & Bastion", - "text": "Configure a jumbox and Azure Bastion", - "waf": "Performance" + "subcategory": "Active Directory", + "text": "Create a dedicated user account with only permissions to join VM to the domain", + "waf": "Security" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Provides secure / seamless RDP/SSH connectivity to your vm's directly through the portal.", - "guid": "ba430d58-4541-085c-3641-068c00be9bc5", - "id": "B05.03", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "Avoid granting access per user, instead use AD groups and replicate them using Active Directory Connector (ADC) in Microsoft Entra ID (former Azure AD). ", + "guid": "2d41e361-1cc5-47b4-a4b1-410d43958a8c", + "id": "D01.06", + "link": "https://docs.microsoft.com/azure/virtual-desktop/manage-app-groups", "services": [ - "VM", - "AVS", - "Bastion" + "AVD", + "Entra" ], "severity": "Medium", - "subcategory": "Jumpbox & Bastion", - "text": "Security measure allowing RDP access via the portal", - "waf": "Performance" + "subcategory": "Active Directory", + "text": "Create a domain user group for each set of users that will be granted access to each Host Pool Application Group (DAG or RAG)", + "waf": "Security" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Using a VPN to connect to Azure to enable VMware communications (HCX) (not recommended)", - "guid": "9988598f-2a9f-6b12-9b46-488415ceb325", - "id": "B06.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-site-to-site-vpn-gateway", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "If Azure Files Active Directory (AD) integration is used, as part of the configuration procedure, an AD account to represent the storage account (file share) will be created. You can choose to register as a computer account or service logon account, see FAQ for details. For computer accounts, there is a default password expiration age set in AD at 30 days. Similarly, the service logon account may have a default password expiration age set on the AD domain or Organizational Unit (OU). For both account types, we recommend you check the password expiration age configured in your AD environment and plan to update the password of your storage account identity of the AD account before the maximum password age. You can consider creating a new AD Organizational Unit (OU) in AD and disabling password expiration policy on computer accounts or service logon accounts accordingly.", + "guid": "2289b3d6-b57c-4fc6-9546-1e1a3e3453a3", + "id": "D01.07", + "link": "https://docs.microsoft.com/azure/storage/files/storage-files-identity-ad-ds-enable", "services": [ - "AVS", - "VPN" + "AVD", + "Storage", + "Entra", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "VPN", - "text": "Connect to Azure using a VPN", - "waf": "Performance" + "severity": "High", + "subcategory": "Active Directory", + "text": "Review your organization password expiration policy for accounts used by Azure Files AD integration", + "waf": "Security" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use the migration assesment tool and timeline to determine bandwidth required (eg 3rd party tool in link)", - "guid": "956ce5e9-a862-fe2b-a50d-a22923569357", - "id": "B06.02", - "link": "https://www.omnicalculator.com/other/data-transfer#:~:text=To%20calculate%20the%20data%20transfer%20speed%3A%201%20Download,measured%20time%20to%20find%20the%20data%20transfer%20speed.", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "You can configure this using Active Directory Connect (ADC) or Azure AD Domain Services (for hybrid or cloud organizations). Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", + "guid": "5119bf8e-8f58-4542-a7d9-cec166cd072a", + "id": "D01.08", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", "services": [ - "AVS", - "VPN" + "AVD", + "Entra" ], - "severity": "Medium", - "subcategory": "VPN", - "text": "Bandwidth sizing", - "waf": "Performance" + "severity": "High", + "subcategory": "Active Directory", + "text": "A Windows Server Active Directory forest/domain must be in sync with Microsoft Entra ID", + "waf": "Reliability" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "What traffic is routed through a firewall, what goes directly into Azure", - "guid": "e095116f-0bdc-4b51-4d71-b9e469d56f59", - "id": "B06.03", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "If Azure Files is used and pre-requisites can be satisfied, it is recommended to configure (Microsoft Entra ID) Kerberos authentication. This configuration will allow to store FSLogix profiles that can be accessed by hybrid user identities from Azure AD-joined session hosts without requiring network line-of-sight to domain controllers.", + "guid": "e777fd5e-c5f1-4d6e-8fa9-fc210b88e338", + "id": "D02.01", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-identity-auth-hybrid-identities-enable", "services": [ - "AVS", - "VPN" + "AVD", + "Storage", + "Entra" ], "severity": "Medium", - "subcategory": "VPN", - "text": "Traffic routing ", - "waf": "Performance" + "subcategory": "Microsoft Entra ID", + "text": "Configure Azure Files share for Microsoft Entra ID (former Azure AD) Kerberos authentication on Microsoft Entra ID Joined scenario", + "waf": "Security" }, { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Name and unique address space for the vWAN, name for the vWAN hub", - "guid": "4dc480ac-cecd-39c4-fdc6-680b300716ab", - "id": "B07.01", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-site-to-site-portal#openvwan", + "category": "Identity", + "checklist": "Azure Virtual Desktop Review", + "description": "An Azure subscription must be parented to the same Microsoft Entra ID (former Azure AD) tenant, that contains a virtual network that either contains or is connected to the Windows Server Active Directory Domain Services or Microsoft Entra ID Domain Services instance.", + "guid": "6ceb5443-5125-4922-9442-93bb628537a5", + "id": "D03.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", "services": [ - "AVS", - "VWAN" + "AVD", + "Subscriptions", + "VNet", + "Entra" ], - "severity": "Medium", - "subcategory": "vWAN hub", - "text": "vWAN name, hub name and address space", - "waf": "Performance" - }, - { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Select either boh or the appropriate connection type.", - "guid": "51d6affd-8e02-6aea-d3d4-0baf618b3076", - "id": "B07.02", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-point-to-site-portal", - "services": [ - "AVS", - "VPN", - "VWAN" - ], - "severity": "Medium", - "subcategory": "vWAN hub", - "text": "ExR and/or VPN gateway provisioned", - "waf": "Performance" - }, - { - "category": "Connectivity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Add Azure firewall to vWAN (recommended)", - "guid": "e32a4c67-3dc0-c134-1c12-52d46dcbab5b", - "id": "B07.03", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-expressroute-portal", - "services": [ - "Firewall", - "AVS", - "VWAN" - ], - "severity": "Medium", - "subcategory": "vWAN hub", - "text": "Secure vWAN", - "waf": "Security" + "severity": "High", + "subcategory": "Requirements", + "text": "A Microsoft Entra ID tenant must be available with at least one subscription linked", + "waf": "Reliability" }, { "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Active directory or other identity provider servers", - "guid": "fbc47fbf-bc96-fa93-ed5d-8c9be63cd5c3", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Virtual Desktop supports different types of identities depending on which configuration you choose. Please review the supported scenarios mentioned in the 'More Info' article and document the design decision accordingly in the 'Comment' column. Critically, external identities (B2B or B2C) are not supported. Be sure to review also the list of supported scenarios in https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios.", + "guid": "b4ce4781-7557-4a1f-8043-332ae199d44c", + "id": "D03.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication", "services": [ - "AVS", + "AVD", "Entra" ], - "severity": "Medium", - "subcategory": "Access", - "text": "External Identity (user accounts)", + "severity": "High", + "subcategory": "Requirements", + "text": "Review and document your identity scenario", "waf": "Security" }, { "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Not required for LDAPS, required for Kerberos", - "guid": "b5db7975-f6bb-8ba3-ee5f-e3e805887997", - "id": "C01.02", - "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", + "checklist": "Azure Virtual Desktop Review", + "description": "Users need accounts that are in Microsoft Entra ID (former Azure AD). If you're also using AD DS or Azure AD Domain Services in your deployment of Azure Virtual Desktop, these accounts will need to be hybrid identities, which means the user accounts are synchronized. If you're using Microsoft Entra ID with AD DS, you'll need to configure Azure AD Connect to synchronize user identity data between AD DS and Microsoft Entra ID. If you're using Microsoft Entra ID with Azure AD Domain Services, user accounts are synchronized one way from Microsoft Entra ID to Azure AD Domain Services. This synchronization process is automatic. AVD also supports Microsoft Entra ID native accounts with some restrictions. External identities (B2B or B2C) are not supported.", + "guid": "f9b141a8-98a5-435e-9378-97e71ca7da7b", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", "services": [ - "AVS", + "AVD", "Entra" ], "severity": "Medium", - "subcategory": "Access", - "text": "If using AD domain, ensure Sites & Services has been configured", + "subcategory": "Requirements", + "text": "Assess User Account types and requirements", "waf": "Security" }, { "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Authentication for users, must be secure.", - "guid": "c30749c4-e2af-558c-2eb9-0b6ae84881d1", - "id": "C01.03", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD supports SSO using either Active Directory Federation Services (AD FS) or Microsoft Entra ID (former Azure AD) authentication. The latter is recommended, please check the requirements and limitation in the 'More Info' article. Using AD FS could be a viable choice if already present in the customer environment, it is not recommended to deploy a brand new ADFS infrastructure just for AVD SSO implementation.", + "guid": "5f9f680a-ba07-4429-bbf7-93d7071561f4", + "id": "D03.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication#single-sign-on-sso", "services": [ - "AVS", + "AVD", "Entra" ], "severity": "Medium", - "subcategory": "Access", - "text": "Use LDAPS not ldap ( vCenter)", - "waf": "Security" + "subcategory": "Requirements", + "text": "If Single-Sign On (SSO) is a requirement, review the supported scenarios and prerequisites", + "waf": "Reliability" }, { "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Authentication for users, must be secure.", - "guid": "64cb9b5c-9edd-787e-1dd8-2b2338e51635", - "id": "C01.04", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-external-identity-source-nsx-t", + "checklist": "Azure Virtual Desktop Review", + "description": "VMs can be Windows Active Directory (AD) domain-joined, Hybrid AD-joined, Microsoft Entra ID (former Azure AD) Joined or Azure AD Domain Services joined. Be sure to review supported scenarios, limitations and requirements from the referenced article.", + "guid": "ea962a15-9394-46da-a7cc-3923266b2258", + "id": "D03.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", "services": [ - "AVS", + "AVD", + "VM", "Entra" ], - "severity": "Medium", - "subcategory": "Access", - "text": "Use LDAPS not ldap (NSX-T)", + "severity": "High", + "subcategory": "Requirements", + "text": "Select the proper AVD Session Host domain join type", "waf": "Security" }, { "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "CN or SAN names, no wildcards, contains private key - CER or PFX", - "guid": "bec285ab-037e-d629-81d1-f61dac23cd4c", - "id": "C02.01", - "link": "https://youtu.be/4jvfbsrhnEs", + "checklist": "Azure Virtual Desktop Review", + "description": "Compare self-managed Windows Active Directory Domain Services, Microsoft Entra ID (former Azure AD), and managed Azure AD Domain Services (AAD-DS)", + "guid": "6f4a1651-bddd-4ea8-a487-cdeb4861bc3b", + "id": "D03.06", + "link": "https://docs.microsoft.com/azure/active-directory-domain-services/compare-identity-solutions", "services": [ - "AVS", + "AVD", "Entra" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Security certificate installed on LDAPS servers ", - "waf": "Security" + "severity": "Low", + "subcategory": "Requirements", + "text": "Before using Azure AD Domain Services (AAD-DS) for AVD, be sure to review the limitations.", + "waf": "Reliability" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Standard Azure Roles Based Access Controls", - "guid": "4ba394a2-3c33-104c-8e34-2dadaba9cc73", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD provides administrative templates for Intune and Active Directory GPO. Using these templates it is possible to centrally control several AVD configuration settings: Graphics related data logging, Screen capture protection, RDP Shortpath for managed networks, Watermarking. See companion article in 'More Info' colum for details. NOTE: FSLogix has its own separate template.", + "guid": "5549524b-36c0-4f1a-892b-ab3ca78f5db2", + "id": "E01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/administrative-template", "services": [ - "AVS", - "RBAC", - "Entra" + "AVD", + "Entra", + "Monitor" ], - "severity": "Medium", - "subcategory": "Security", - "text": "RBAC applied to Azure roles", - "waf": "Security" + "severity": "Low", + "subcategory": "Management", + "text": "Use built-in provided administrative templates for AVD settings configuration", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create roles in vCenter required to meet minimum viable access guidelines", - "guid": "b04ca129-83a9-3494-7512-347dd2d766db", - "id": "C02.03", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity#view-the-vcenter-server-privileges", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Determine if a configuration management tool is already in place to manage Host Pool VM configuration after initial deployment, For example SCCM/SCOM, Intune/ConfigurationManager, 3rd-party solutions.", + "guid": "3334fdf9-1c23-4418-8b65-285269440b4b", + "id": "E01.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/management", "services": [ - "AVS", - "RBAC", - "Entra" + "AVD", + "VM", + "Monitor" ], - "severity": "Medium", - "subcategory": "Security", - "text": "RBAC model in vCenter", - "waf": "Security" + "severity": "Low", + "subcategory": "Management", + "text": "Plan AVD Session Hosts configuration management strategy", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", - "guid": "8e477d2f-8004-3dd0-93d6-0aece9e1b2fb", - "id": "C02.04", - "link": "Best practice", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "We recommend using Microsoft Intune, if requirements can be satisfied, to manage your Azure Virtual Desktop environment. Review supported scenarios and requirements to enable Intune for AVD Session Host management in the referenced article in the “More Info” column. Document your choice in the 'Comment' column. In that article, review the different requirements and capabilities for single-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop and multi-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session AVD.", + "guid": "63a08be1-6004-4b4a-a79b-f3239faae113", + "id": "E01.03", + "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop", "services": [ - "AVS", - "RBAC", - "Entra" + "AVD", + "Monitor" ], "severity": "Medium", - "subcategory": "Security", - "text": "CloudAdmin role usage", - "waf": "Security" + "subcategory": "Management", + "text": "Evaluate Intune for AVD Session Hosts management", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", - "guid": "00e0b729-f9be-f600-8c32-5ec0e8f2ed63", - "id": "C03.01", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "The scaling tool provides a low-cost automation option for customers who want to optimize their session host VM costs. You can use the scaling tool to schedule VMs to start and stop based on Peak and Off-Peak business hours, scale out VMs based on number of sessions per CPU core, scale in VMs during Off-Peak hours, leaving the minimum number of session host VMs running. Not available yet for Personal Host Pool type.", + "guid": "7138b820-102c-4e16-be30-1e6e872e52e3", + "id": "E01.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/autoscale-scenarios", "services": [ - "AVS", - "Entra", - "RBAC" + "AVD", + "VM", + "Cost", + "Monitor" ], "severity": "Medium", - "subcategory": "Security ", - "text": "Is Privileged Identity Management implemented", - "waf": "Security" + "subcategory": "Management", + "text": "Assess the requirements for host pool auto-scaling capability", + "waf": "Reliability" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For the Azure VMware Solution PIM roles", - "guid": "0842d45f-41a8-8274-1155-2f6ed554d315", - "id": "C03.02", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Start VM On Connect lets you reduce costs by enabling end users to turn on their session host virtual machines (VMs) only when they need them. You can then turn off VMs when they're not needed. You can configure Start VM on Connect for personal or pooled host pools using the Azure portal or PowerShell. Start VM on Connect is a host pool wide setting.", + "guid": "55f612fe-f215-4f0d-a956-10e7dd96bcbc", + "id": "E01.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect", "services": [ - "AVS", - "Entra", - "RBAC" + "AVD", + "VM", + "Cost", + "Monitor" ], - "severity": "Medium", - "subcategory": "Security ", - "text": "Is Privileged Identity Management audit reporting implemented", - "waf": "Security" + "severity": "Low", + "subcategory": "Management", + "text": "Consider the usage of Start VM on Connect for Personal Host Pools", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Best practice, also see Monitoring/Alerts", - "guid": "915cbcd7-0640-eb7c-4162-9f33775de559", - "id": "C03.03", - "link": "Best practice", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "'Start VM On Connect' provides a smart way to automatically start previously stopped Session Hosts but does not provide a mechanism to shut down when not in used. Administrators are encouraged to configure additional policies to sign users out of their sessions and run Azure automation scripts to de-allocate VMs. Users should be not allowed to shut down their Personal Hosts since will not be able to de-allocate Azure VMs, then billing will still be active with no cost reduction.", + "guid": "79a686ea-d971-4ea0-a9a8-1aea074c94cb", + "id": "E01.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect-faq#are-vms-automatically-deallocated-when-a-user-stops-using-them", "services": [ - "AVS", - "Entra", - "Monitor" + "Monitor", + "VM", + "AzurePolicy", + "AVD", + "Cost" ], - "severity": "Medium", - "subcategory": "Security ", - "text": "Limit use of CloudAdmin account to emergency access only", - "waf": "Security" + "severity": "Low", + "subcategory": "Management", + "text": "Evaluate the implementation of an ad-hoc mechanism to shut down Personal AVD Session Hosts", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Operational procedure", - "guid": "7effa0c0-9172-e8e4-726a-67dbea8be40a", - "id": "C03.04", - "link": "https://learn.microsoft.com/azure/azure-vmware/rotate-cloudadmin-credentials?tabs=azure-portal", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Virtual Desktop billing is mainly based on cost associated to compute, networking and storage resources consumed by Host Pools. In addition to this, costs can be generated by dependent resources, for example VPN or ExpressRoute or vWAN, Active Directory Domain Controllers, DNS, etc. There is no direct cost associated to AVD objects like workspaces, host pools or application groups. To make AVD associated costs more evident and grouped by Host Pool, it is recommended to use 'cm-resource-parent' tag. ", + "guid": "51bcafca-476a-48fa-9b91-9645a7679f20", + "id": "E01.07", + "link": "https://learn.microsoft.com/azure/virtual-desktop/tag-virtual-desktop-resources", "services": [ - "AVS", - "Entra" + "VWAN", + "DNS", + "Storage", + "Monitor", + "VPN", + "ExpressRoute", + "AVD", + "Cost" ], - "severity": "Medium", - "subcategory": "Security ", - "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", - "waf": "Security" + "severity": "Low", + "subcategory": "Management", + "text": "Review and adopt suggested Azure Tags for Azure Virtual Desktop", + "waf": "Cost" }, { - "category": "Management", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", - "guid": "8f426fd0-d73b-d398-1f6f-df0cbe262a82", - "id": "D01.01", - "link": "https://learn.microsoft.com/azure/azure-arc/vmware-vsphere/overview", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Advisor analyzes your configurations and telemetry to offer personalized recommendations to solve common problems. With these recommendations, you can optimize your Azure resources for reliability, security, operational excellence, performance, and cost.", + "guid": "611dd68c-5a4b-4252-8e44-a59a9c2399c4", + "id": "E01.08", + "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-advisor-recommendations", "services": [ - "VM", - "AVS", - "Arc" + "AVD", + "Cost", + "Entra", + "Monitor" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "AVS VM Management (Azure Arc)", + "severity": "Low", + "subcategory": "Management", + "text": "Periodically check Azure Advisor recommendations for AVD", "waf": "Operations" }, { - "category": "Management", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", - "guid": "11dbe773-e380-9191-1418-e886fa7a6fd0", - "id": "D01.02", - "link": "https://docs.microsoft.com/azure/governance/policy/overview", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Customers have several options: Microsoft Configuration Manager, this article explains how to automatically apply updates to a Azure Virtual Desktop session hosts running Windows 10/11: https://learn.microsoft.com/azure/virtual-desktop/configure-automatic-updates, Microsoft Intune: https://docs.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session, Azure Update Management and WSUS for Windows Server OS only (client OS not supported: https://learn.microsoft.com/azure/automation/update-management/operating-system-requirements), 3rd Party tools. Outside an emergency security patching situation, it is recommended to move away from an 'in-place' update strategy patching strategy and adopt a re-imaging approach.", + "guid": "04722da2-9c2b-41cd-922f-54b29bade3aa", + "id": "E01.09", + "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop-multi-session", "services": [ - "AVS", - "AzurePolicy", + "AVD", "Monitor" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Azure policy", + "subcategory": "Management", + "text": "Plan for a Session Host emergency patching and update strategy", "waf": "Operations" }, { - "category": "Management", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", - "guid": "1e59c639-9b7e-a60b-5e93-3798c1aff5db", - "id": "D01.03", - "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json#configure-locks", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "The Scheduled Agent Updates feature lets you create up to two maintenance windows per Host Pool to update AVD components at a convenient time. It is recommended to specify maintenance windows then upgrading Session Hosts will not happen during peak business hours. Scheduled Agent Updates is disabled by default. This means that, unless you enable this setting, the agent can get updated at any time by the agent update flighting service.", + "guid": "c067939b-e5ca-4698-b9ce-3bd91843e73f", + "id": "E01.10", + "link": "https://learn.microsoft.com/azure/virtual-desktop/scheduled-agent-updates", "services": [ - "AVS" + "AVD", + "Monitor" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Resource locks", - "waf": "Operations" + "severity": "Low", + "subcategory": "Management", + "text": "Configure the Scheduled Agent Updates feature", + "waf": "Reliability" }, { - "category": "Management", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For manual deployments, all configuration and deployments must be documented", - "guid": "8f2c46aa-ca1b-cad3-3ac9-213dfc0a265e", - "id": "D01.04", - "link": "Make sure to create your own runbook on the deployment of AVS.", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Host pools are a collection of one or more identical virtual machines within Azure Virtual Desktop environment. We highly recommend you create a validation host pool where service updates are applied first. This allows you to monitor service updates before the service applies them to your standard or non-validation environment.", + "guid": "d1e8c38e-c936-4667-913c-005674b1e944", + "id": "E01.11", + "link": "https://docs.microsoft.com/azure/virtual-desktop/create-validation-host-pool", "services": [ - "AVS" + "AVD", + "VM", + "Monitor" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Run books", + "subcategory": "Management", + "text": "Create a validation (canary) Host Pool", "waf": "Operations" }, { - "category": "Management", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", - "guid": "86b314f9-1f1e-317a-4dfb-cf510ad4a030", - "id": "D01.05", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "An AVD Host Pool can be deployed in several ways: Azure Portal, ARM templates, Azure CLI tool, Powershell, manual VM creation with registration token, Terraform, 3rd-party tools. It is important to adopt proper method/s to support automatic deployment through automation and CI/CD tools.", + "guid": "a459c373-e7ed-4616-83b3-65a917ecbe48", + "id": "E01.12", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-platform-automation-and-devops", "services": [ - "AVS", - "AKV" + "AVD", + "VM", + "Monitor" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Naming conventions for auth keys", + "subcategory": "Management", + "text": "Determine Host Pool deployment strategy", "waf": "Operations" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "For automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", - "guid": "e22a2d99-eb71-7d7c-07af-6d4cdb1d4443", - "id": "E01.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "After you register a VM to a host pool within the Azure Virtual Desktop service, the agent regularly refreshes the VM's token whenever the VM is active. The certificate for the registration token is valid for 90 days. Because of this 90-day limit, we recommend VMs to be online for 20 minutes every 90 days so that the machine can refresh its tokens and update the agent and side-by-side stack components.", + "guid": "ebe54cd7-df2e-48bb-ac35-81559bb9153e", + "id": "E01.13", + "link": "https://docs.microsoft.com/azure/virtual-desktop/faq", "services": [ - "AVS", + "AVD", + "VM", "Monitor" ], "severity": "Medium", - "subcategory": "Alerts", - "text": "Create warning alerts for critical thresholds ", + "subcategory": "Management", + "text": "Turn on Session Host VMs at least every 90 days for token refresh", "waf": "Operations" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", - "guid": "6d02f159-627d-79bf-a931-fab6d947eda2", - "id": "E01.02", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Virtual Desktop Insights is a dashboard built on Azure Monitor Workbooks that helps IT professionals understand their Azure Virtual Desktop environments. Read the referenced article to learn how to set up Azure Monitor for Azure Virtual Desktop to monitor your AVD environments.", + "guid": "63cfff1c-ac59-49ef-8d5a-83dd4de36c1c", + "id": "E02.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/insights", "services": [ - "AVS", + "AVD", "Monitor" ], - "severity": "Medium", - "subcategory": "Alerts", - "text": "Create critical alert vSAN consumption", - "waf": "Operations" + "severity": "High", + "subcategory": "Monitoring", + "text": "Enable monitoring for AVD", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Provides platform alerts (generated by Microsoft)", - "guid": "1cc97b39-2c7e-246f-6d73-789cfebfe951", - "id": "E01.03", - "link": "https://www.virtualworkloads.com/2021/04/azure-vmware-solution-azure-service-health/", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "Azure Virtual Desktop uses Azure Monitor and Log Analytics for monitoring and alerts like many other Azure services. This lets admins identify issues through a single interface. The service creates activity logs for both user and administrative actions. Each activity log falls under the following categories: Management, Feed, Connections, Host Registration, Errors, Checkpoints. ", + "guid": "81770afb-c4c0-4e43-a186-58d2857ed671", + "id": "E02.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics", "services": [ - "AVS", + "AVD", + "VM", "Monitor" ], "severity": "Medium", - "subcategory": "Alerts", - "text": "Configured for Azure Service Health alerts and notifications", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Enable diagnostic settings for Workspaces, Host Pools, Application Groups and Host VMs to Log Analytics workspace", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", - "guid": "0962606c-e3b4-62a9-5661-e4ffd62a4509", - "id": "E02.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "See the referenced article and this additional one to setup proper monitoring and alerting for storage: https://docs.microsoft.com/azure/storage/files/storage-troubleshooting-files-performance. ", + "guid": "2463cffe-179c-4599-be0d-5973dd4ce32c", + "id": "E02.03", + "link": "https://docs.microsoft.com/azure/storage/files/storage-files-monitoring?tabs=azure-portal", "services": [ - "VM", - "Monitor", - "Backup", - "AVS", - "AzurePolicy" + "AVD", + "Storage", + "Monitor" ], "severity": "Medium", - "subcategory": "Backup", - "text": "Backup policy", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Create alerts on the profile storage to be alerted in case of high usage and throttling", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Keep in mind the lead time for requesting new nodes", - "guid": "4ec7ccfb-795e-897e-4a84-fd31c04eadc6", - "id": "E03.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "category": "Monitoring and Management", + "checklist": "Azure Virtual Desktop Review", + "description": "You can use Azure Service Health to monitor service issues and health advisories for Azure Virtual Desktop. Azure Service Health can notify you with different types of alerts (for example, email or SMS), help you understand the effect of an issue, and keep you updated as the issue resolves.", + "guid": "18813706-f7c4-4c0d-9e51-4548d2457ed6", + "id": "E02.04", + "link": "https://docs.microsoft.com/azure/virtual-desktop/set-up-service-alerts", "services": [ - "AVS", - "AzurePolicy", + "AVD", "Monitor" ], "severity": "Medium", - "subcategory": "Capacity", - "text": "Policy around ESXi host density and efficiency", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Configure Azure Service Health for AVD alerts ", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Azure Cost Management can be used - one option, put AVS in it's own Subscription. ", - "guid": "7f8f175d-13f4-5298-9e61-0bc7e9fcc279", - "id": "E04.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/govern", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "If required to connect to on-premises environment, assess the current connectivity option or plan for the required connectivity (ExpressRoute, Azure S2S or 3rd-party NVA VPN). ", + "guid": "dd399cfd-7b28-4dc8-9555-6202bfe4563b", + "id": "F01.01", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", "services": [ - "Subscriptions", - "Monitor", - "AVS", - "Cost" + "ExpressRoute", + "AVD", + "VPN", + "NVA" ], "severity": "Medium", - "subcategory": "Costs", - "text": "Ensure a good cost management process is in place for Azure VMware Solution - ", - "waf": "Operations" + "subcategory": "Networking", + "text": "Determine if hybrid connectivity is required to connect to on-premises environment", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Create dashboards to enable core Azure VMware Solution monitoring insights", - "guid": "01e689e0-7c6c-b58f-37bd-4d6b9b1b9c74", - "id": "E05.01", - "link": "https://docs.microsoft.com/azure/azure-portal/azure-portal-dashboards", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD Host Pools can be deployed in either Azure Virtual WAN or traditional 'Hub & Spoke' network topologies. It is recommended to deploy each Host Pool in a separate 'spoke' VNet, using 'hub' is not recommended.", + "guid": "c8639648-a652-4d6c-85e5-02965388e5de", + "id": "F01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-network-topology-and-connectivity", "services": [ - "AVS", - "NetworkWatcher", - "Monitor" + "AVD", + "VNet", + "VWAN" ], "severity": "Medium", - "subcategory": "Dashboard", - "text": "Connection monitor dashboard", - "waf": "Operations" + "subcategory": "Networking", + "text": "Determine Azure Virtual Network (VNet) placement for each AVD Host Pool", + "waf": "Performance" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Send to an Azure Storage account or Azure EventHub for processing (direct to Log Analytics is pending)", - "guid": "f9afdcc9-649d-d840-9fb5-a3c0edcc697d", - "id": "E06.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Evaluate the bandwidth requirements, ensure VPN/ER bandwidth will be enough, ensure proper routing and firewall rules are in place, test end-to-end latency. ", + "guid": "d227dd14-2b06-4c21-a799-9a646f4389a7", + "id": "F01.03", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", "services": [ - "AVS", - "Storage", - "Monitor" + "AVD", + "VPN" ], "severity": "Medium", - "subcategory": "Logs & Metrics", - "text": "Configure Azure VMware Solution logging ", - "waf": "Operations" + "subcategory": "Networking", + "text": "Assess which on-premises resources are required from AVD Host Pools", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Must be on-premises, implement if available", - "guid": "7cbac8c3-4eda-d5d9-9bda-c6b5abba9fb6", - "id": "E06.02", - "link": "Is vROPS or vRealize Network Insight going to be used? ", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Several options are available. You can use Azure Firewall or equivalent 3rd-party NVA, Network Security Group (NSG) and/or Proxy servers. NSG is not able to enable/disable by URL, only ports and protocols. Proxy should be used only as explicit setting in user browser. Details on using Azure Firewall Premium with AVD are reported in the companion article in the 'More Info' column. Be sure to allow proper access to required AVD URLs. Forced Tunneling to on-premises is not recommended.", + "guid": "fc4972cd-3cd2-41bf-9703-6e5e6b4bed3d", + "id": "F01.04", + "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", "services": [ - "AVS", - "Monitor" + "Firewall", + "AVD", + "VNet", + "NVA" ], "severity": "Medium", - "subcategory": "Logs & Metrics", - "text": "vRealize Operations", - "waf": "Operations" + "subcategory": "Networking", + "text": "Need to control/restrict Internet outbound traffic for AVD hosts?", + "waf": "Security" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", - "guid": "b243521a-644d-f865-7fb6-21f9019c0dd2", - "id": "E06.03", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Required URLs for AVD control plane access by session hosts are documented here: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list. A check tool is available to verify connectivity from the session hosts: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list#required-url-check-tool. Forced Tunneling to on-premises is not recommended.", + "guid": "65c7acbe-45bb-4e60-ad89-f2e87778424d", + "id": "F01.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/safe-url-list", "services": [ - "VM", - "AVS", - "Monitor" + "AVD" ], - "severity": "Medium", - "subcategory": "Logs & Metrics", - "text": "AVS VM logging", - "waf": "Operations" + "severity": "High", + "subcategory": "Networking", + "text": "Ensure AVD control plane endpoints are accessible", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Between on-premises to Azure are monitored using 'connection monitor'", - "guid": "2ca97d91-dd36-7229-b668-01036ccc3cd3", - "id": "E07.01", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Consider the usage of Azure Defender Endpoint or similar 3rd-party agents to control user web navigation, see the Security section for more details.", + "guid": "73676ae4-6691-4e88-95ad-a42223e13810", + "id": "F01.06", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/onboard-windows-multi-session-device?view=o365-worldwide", "services": [ - "VPN", - "NetworkWatcher", - "Monitor", - "ExpressRoute", - "AVS" + "AVD", + "Defender" ], "severity": "Medium", - "subcategory": "Network", - "text": "Monitor ExpressRoute and/or VPN connections ", - "waf": "Operations" + "subcategory": "Networking", + "text": "Need to control/restrict Internet outbound traffic only for users on AVD hosts? ", + "waf": "Security" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To monitor the Azure VMware Solution back-end ExpressRoute connection (Azure native to AVS)", - "guid": "99209143-60fe-19f0-5633-8b5671277ba5", - "id": "E07.02", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Custom UDR and NSG can be applied to AVD Host Pool subnets, for example to redirect to Azure Firewall or NVA, or to filter/block network traffic. In this case is recommended to carefully review to ensure optimal path for outbound traffic to AVD control plane is used. Service Tags can now be used with UDR and NSG, then AVD management plane traffic can be easily allowed: https://learn.microsoft.com/azure/virtual-desktop/safe-url-list.", + "guid": "523181a9-4174-4158-93ff-7ae7c6d37431", + "id": "F01.07", + "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", "services": [ - "AVS", - "ExpressRoute", - "Monitor" + "Firewall", + "AVD", + "VNet", + "NVA" ], - "severity": "Medium", - "subcategory": "Network", - "text": "Monitor from an Azure native resource to an Azure VMware Solution VM", - "waf": "Operations" + "severity": "Low", + "subcategory": "Networking", + "text": "Review custom UDR and NSG for AVD Host Pool subnets", + "waf": "Security" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To monitor end-to-end, on-premises to AVS workloads", - "guid": "b9e5867c-57d3-036f-fb1b-3f0a71664efe", - "id": "E07.03", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Network traffic from AVD Session Host VMs to AVD control plane should be as direct as possible. Redirecting this traffic through a Proxy or Firewall with deep packet inspection and/or SSL termination could cause serious issues and bad customer experience. It is recommended to bypass Proxy and Firewall just for the AVD control plane. User generated traffic surfing the web instead, should be filtered by Firewall and/or redirected to a Proxy. For details and guidelines, please see the companion article in the 'More Info' column.", + "guid": "cc6edca0-aeca-4566-9e92-cf246f1465af", + "id": "F01.08", + "link": "https://learn.microsoft.com/azure/virtual-desktop/proxy-server-support", "services": [ - "AVS", - "Monitor" + "AVD", + "VM" ], - "severity": "Medium", - "subcategory": "Network", - "text": "Monitor from an on-premises resource to an Azure VMware Solution VM", - "waf": "Operations" + "severity": "High", + "subcategory": "Networking", + "text": "Do not use Proxy servers, SSL termination and Deep Packet Inspection for AVD control plane traffic", + "waf": "Reliability" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Track requests to Azure VMware Solution and Azure VMware Solution based workloads", - "guid": "4af7c5f7-e5e9-bedf-a8cf-314b81735962", - "id": "E08.01", - "link": "Firewall logging and alerting rules are configured (Azure Firewall or 3rd party)", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "It is recommended to assess and review networking bandwidth requirements for users, based on the specific workload type. The referenced article provide general estimations and recommendations, but specific measure are required for proper sizing. ", + "guid": "516785c6-fa96-4c96-ad88-408f372734c8", + "id": "F01.09", + "link": "https://learn.microsoft.com/azure/virtual-desktop/rdp-bandwidth", "services": [ - "AVS", - "Monitor" + "AVD", + "VM" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Auditing and logging is implemented for inbound internet ", - "waf": "Operations" + "severity": "Low", + "subcategory": "Networking", + "text": "Check the network bandwidth required for each user and in total for the VM SKU", + "waf": "Performance" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", - "guid": "74be60a3-cfac-f057-eda6-3ee087e805d5", - "id": "E08.02", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "If Azure Files SMB share will be used to store user profiles via FSLogix, the usage of Private Endpoint (PE) for private access to the storage is recommended. AVD Session Hosts will access the storage using a private IP in the same VNet, a separate subnet is recommended. This feature has an additional cost that must be evaluated. If PE will not be used, at least Service Endpoint is recommended (no cost associated).", + "guid": "ec27d589-9178-426d-8df2-ff60020f30a6", + "id": "F01.10", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-networking-endpoints", "services": [ - "AVS", - "Monitor" + "VNet", + "Storage", + "PrivateLink", + "AVD", + "Cost" ], "severity": "Medium", - "subcategory": "Security", - "text": "Session monitoring ", - "waf": "Operations" + "subcategory": "Networking", + "text": "Evaluate usage Private Endpoint for Azure Files share", + "waf": "Security" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Enable Diagnostic and metric logging on Azure VMware Solution", - "guid": "a434b3b5-f258-0845-cd76-d7df6ef5890e", - "id": "E09.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", + "category": "Networking", + "checklist": "Azure Virtual Desktop Review", + "description": "Connections to Azure Virtual Desktop can use TCP or UDP. RDP Shortpath is a feature of AVD that establishes a direct UDP-based transport between a supported Windows Remote Desktop client and session host. if clients have line of sight to AVD session hosts from internal network (VPN usage is not recommended), this feature can provide lower latency and best performances as explained in https://learn.microsoft.com/azure/virtual-desktop/rdp-shortpath?tabs=managed-networks#key-benefits.", + "guid": "b2074747-d01a-4f61-b1aa-92ad793d9ff4", + "id": "F01.11", + "link": "https://docs.microsoft.com/azure/virtual-desktop/shortpath", "services": [ - "AVS", - "Monitor" + "AVD", + "VPN" ], "severity": "Medium", - "subcategory": "VMWare", - "text": "Logging and diagnostics", - "waf": "Operations" + "subcategory": "Networking", + "text": "Evaluate usage of RDP ShortPath for clients connecting from managed internal networks", + "waf": "Performance" }, { - "category": "Monitoring", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Monitor AVS workloads (each VM in AVS)", - "guid": "fb00b69a-83ec-ce72-446e-6c23a0cab09a", - "id": "E10.01", - "link": "https://docs.microsoft.com/azure/azure-monitor/agents/agent-windows?tabs=setup-wizard", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Security mechanisms provided by GPO should be used, if available. For example, it is possible to impose desktop screen lock and idle session disconnection time. Existing GPOs applied to on-premises environment should be reviewed and eventually applied also to secure also AVD Hosts when joined to the domain.", + "guid": "a135e337-897e-431c-97d6-8cb6a22ac19f", + "id": "G01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#establish-maximum-inactive-time-and-disconnection-policies", "services": [ - "VM", - "AVS", - "Monitor" + "AVD" ], "severity": "Medium", - "subcategory": "VMware", - "text": "Log Analytics Agents deployed on Azure VMware Solution guest VM workloads", - "waf": "Operations" + "subcategory": "Active Directory", + "text": "Review Active Directory GPO to secure RDP sessions", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision on traffic flow", - "guid": "a1354b87-e18e-bf5c-c50b-8ddf0540e971", - "id": "F01.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Microsoft Defender for Endpoint supports Azure Virtual Desktop for Windows 10/11 Enterprise multi-session. Check article for onboarding non-persistent virtual desktop infrastructure (VDI) devices: https://docs.microsoft.com/windows/security/threat-protection/microsoft-defender-atp/configure-endpoints-vdi", + "guid": "b1172576-9ef6-4691-a483-5ac932223ece", + "id": "G02.01", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/deployment-vdi-microsoft-defender-antivirus", "services": [ - "AVS" + "AVD", + "Defender" ], - "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "North/South routing through Az Firewall or 3rd party ", + "severity": "High", + "subcategory": "Host Configuration", + "text": "Ensure anti-virus and anti-malware solutions are used", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", - "guid": "29a8a499-ec31-f336-3266-0895f035e379", - "id": "F01.02", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Disks in Azure are already encrypted at rest by default with Microsoft managed keys. Host VM OS disk encryption is possible and supported using Azure Disk Encryption (ADE - BitLocker) and Disk Encryption Set (DES - Server Side Encryption), the latter is recommended. Encryption of FSLogix storage using Azure Files can be done using SSE on Azure Storage. For OneDrive encryption, see this article: https://docs.microsoft.com/compliance/assurance/assurance-encryption-for-microsoft-365-services.", + "guid": "0fd32907-98bc-4178-adc5-a06ca7144351", + "id": "G02.02", + "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", "services": [ - "AVS" + "AVD", + "VM", + "Storage", + "AKV" ], - "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "East West (Internal to Azure)", + "severity": "Low", + "subcategory": "Host Configuration", + "text": "Assess disk encryption requirements for AVD Session Hosts", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Requires a 3rd party NVA with Azure Route server - Scenario 2 (see link)", - "guid": "ebd3cc3c-ac3d-4293-950d-cecd8445a523", - "id": "F01.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Trusted launch are Gen2 Azure VMs with enhanced security features aimed to protect against “bottom of the stack” threats through attack vectors such as rootkits, boot kits, and kernel-level malware. Recommended to enable and leverage Secure Boot, Virtual TPM (vTPM) and Integrity Monitoring.", + "guid": "36a5a67f-bb9e-4d5b-9547-8c4479816b28", + "id": "G02.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#azure-virtual-desktop-support-for-trusted-launch", "services": [ - "NVA", - "AVS", - "ARS" + "AVD", + "VM", + "Monitor" ], "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "ExR without Global Reach", - "waf": "Operations" + "subcategory": "Host Configuration", + "text": "Enable Trusted launch in Azure Gen2 VM Session Hosts", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", - "guid": "ffb5c5ca-bd89-ff1b-8b73-8a54d503d506", - "id": "F01.04", - "link": "https://learn.microsoft.com/azure/route-server/route-server-faq", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Trusted Launch and Gen2 VM are not only security and performance enhancing features but also system requirements for Windows 11. When building an AVD environment based on Windows 11, it is essential to enable these features.", + "guid": "135d3899-4b31-44d3-bc8f-028871a359d8", + "id": "G02.04", + "link": "https://learn.microsoft.com/windows/whats-new/windows-11-requirements", "services": [ - "AVS", - "ARS" + "AVD", + "VM" ], - "severity": "Medium", - "subcategory": "Hub & Spoke", - "text": "Route server ", - "waf": "Operations" + "severity": "High", + "subcategory": "Host Configuration", + "text": "Enable Trusted Launch and use Gen2 image are system requirements for Windows 11", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Via on-premises, Az Firewall, 3rd Party, NSX-T pubic IP", - "guid": "a4070dad-3def-818d-e9f7-be440d10e7de", - "id": "F02.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-design-public-internet-access", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Displayed content will be automatically blocked or hidden in screenshots. Keep in mind screen sharing will also be blocked when using Teams or other collaboration software which use screen sharing.", + "guid": "a49dc137-7896-4343-b2bc-1a31bf1d30b6", + "id": "G02.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/screen-capture-protection", "services": [ - "AVS" + "AVD" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Egress point(s)", + "severity": "Low", + "subcategory": "Host Configuration", + "text": "Consider enabling screen capture protection to prevent sensitive information from being captured", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Az Firewall, 3rd party NVA, Application Gateway, Azure Frontdoor ", - "guid": "e942c03d-beaa-3d9f-0526-9b26cd5e9937", - "id": "F02.02", - "link": "Research and choose optimal solution for each application", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "If not absolutely required, redirecting drives, printers, and USB devices to a user's local device in a remote desktop session should be disabled or highly restricted. Restrict Windows Explorer access by hiding local and remote drive mappings is also a secure measure to adopt preventing users from discovering unwanted information about system configuration and users.", + "guid": "7ce2cd20-85b4-4f82-828e-6558736ede6a", + "id": "G02.06", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#other-security-tips-for-session-hosts", "services": [ - "FrontDoor", - "AVS", - "NVA", - "AppGW" + "AVD" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Internet facing applications", + "subcategory": "Host Configuration", + "text": "Restrict device redirection and drive mapping", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", - "guid": "e778a2ec-b4d7-1d27-574c-14476b167d37", - "id": "F03.01", - "link": "https://docs.microsoft.com/azure/route-server/route-server-faq#route-server-limits", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "When choosing a deployment model, you can either provide remote users access to entire virtual desktops or only select applications. Remote applications, or RemoteApps, provide a seamless experience as the user works with apps on their virtual desktop. RemoteApps reduce risk by only letting the user work with a subset of the remote machine exposed by the application.", + "guid": "4e25d70e-3924-44f4-b66f-d6cdd4f4a973", + "id": "G03.01", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", "services": [ - "AVS", - "ARS" + "AVD" ], "severity": "Medium", - "subcategory": "Routing", - "text": "When route server Route limit understood? ", + "subcategory": "Management", + "text": "When possible, prefer Remote Apps over Full Desktops (DAG)", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "(VPN Gateway, AppGW, FrontDoor, Load balancer, VMs (etc) (Remove: enabled on ExR/VPN Gateway subnet in Azure)", - "guid": "66c97b30-81b9-139a-cc76-dd1d94aef42a", - "id": "F04.01", - "link": "https://docs.microsoft.com/azure/ddos-protection/manage-ddos-protection", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Web content filtering feature provided by Web Protection capability in Microsoft Defender for Endpoint, can be used to to control user web navigation. If this tool is used, configuration of web filtering for user Internet browsing is recommended. Access by the Guest OS system to required AVD control plane URLs must be guaranteed.", + "guid": "e19dd344-29eb-4722-a237-a151c5bb4e4f", + "id": "G03.02", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", "services": [ - "VM", - "VPN", - "VNet", - "FrontDoor", - "ExpressRoute", - "AppGW", - "AVS", - "DDoS", - "LoadBalancer" + "AVD", + "Defender" ], "severity": "Medium", - "subcategory": "Security", - "text": "Is DDoS standard protection of public facing IP addresses? ", + "subcategory": "Management", + "text": "Need to control/restrict user Internet navigation from AVD session hosts?", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To manage Azure VMware Solution, vCenter, NSX manager and HCX manager", - "guid": "d43da920-4ecc-a4e9-dd45-a2986ce81d32", - "id": "F04.02", - "link": "Best practice: Bastion or 3rd party tool", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "We recommend you don't grant your users admin access to virtual desktops. If you need software packages, we recommend you make them available through configuration management utilities.", + "guid": "a0cdb3b5-4eb2-4eb0-9dda-a3592718e2ed", + "id": "G03.03", + "link": "https://docs.microsoft.com/azure/virtual-desktop/security-guide", "services": [ - "AVS" + "AVD" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Use a dedicated privileged access workstation (PAW)", + "severity": "High", + "subcategory": "Management", + "text": "Ensure AVD users will not have local administrator privileges on AVD Hosts", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use NSX-T for inter-vmware-traffic inspection", - "guid": "a2dac74f-5380-6e39-25e6-f13b99ece51f", - "id": "F05.01", - "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-F6685367-7AA1-4771-927E-ED77727CFDA3.html", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "We recommend you enable Defender for Cloud for the subscriptions, virtual machines, key vaults, and storage accounts used by AVD. With this tool is possible to assess and manage vulnerabilities, assess compliance with common frameworks like PCI, strengthen the overall security of your AVD environment and measure it over time using 'Secure Score': https://learn.microsoft.com/azure/virtual-desktop/security-guide#improve-your-secure-score.", + "guid": "1814387e-5ca9-4c26-a9b3-2ab5bdfc6998", + "id": "G03.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#enable-microsoft-defender-for-cloud", "services": [ - "AVS" + "Defender", + "VM", + "Storage", + "AKV", + "Subscriptions", + "AVD" ], "severity": "Medium", - "subcategory": "Traffic Inspection", - "text": "East West (Internal to AVS)", + "subcategory": "Management", + "text": "Enable Microsoft Defender for Cloud to manage AVD Session Hosts security posture", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision on whether or not to use Secure hub for E/W and Internet traffic - requires Global Reach", - "guid": "3f621543-dfac-c471-54a6-7b2849b6909a", - "id": "F06.01", - "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Enabling audit log collection lets you view user and admin activity related to Azure Virtual Desktop and store in a central repository like Log Analytics workspace. ", + "guid": "a0916a76-4980-4ad0-b278-ee293c1bc352", + "id": "G03.05", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#collect-audit-logs", "services": [ - "Firewall", - "AVS", - "VWAN" + "AVD", + "Entra", + "Monitor" ], "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Use Secure Hub (Azure Firewall or 3rd party)", + "subcategory": "Management", + "text": "Enable diagnostic and audit logging", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", - "guid": "d7af5670-1b39-d95d-6da2-8d660dfbe16b", - "id": "F06.02", - "link": "https://learn.microsoft.com/azure/firewall-manager/secure-cloud-network", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Assign the least privilege required by defining administrative, operations, and engineering roles to Azure RBAC roles. To limit access to high privilege roles within your Azure Virtual Desktop landing zone, consider integration with Azure Privileged Identity Management (PIM). Maintaining knowledge of which team is responsible for each particular administrative area helps you determine Azure role-based access control (RBAC) roles and configuration.", + "guid": "baaab757-1849-4ab8-893d-c9fc9d1bb73b", + "id": "G03.06", + "link": "https://docs.microsoft.com/azure/virtual-desktop/rbac", "services": [ - "AVS", - "VWAN" + "AVD", + "RBAC", + "Entra" ], - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "East West (Internal to Azure)", + "severity": "Low", + "subcategory": "Management", + "text": "Assess the requirement to use custom RBAC roles for AVD management", "waf": "Security" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", - "guid": "7d049005-eb35-4a93-50a5-3b31a9f61161", - "id": "G01.01", - "link": "https://docs.microsoft.com/azure/azure-vmware/configure-nsx-network-components-azure-portal", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "AVD users should not have permission to install application. If required, Windows Defender Application Control (WDAC) can be used to control which drivers and applications are allowed to run on their Windows clients. ", + "guid": "b9ea80c8-0628-49fc-ae63-125aa4c0a284", + "id": "G03.07", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#windows-defender-application-control", "services": [ - "Subscriptions", - "AVS" + "AVD", + "Defender" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale out operations planning", - "waf": "Performance" + "subcategory": "Management", + "text": "Restrict users from installing un-authorized applications", + "waf": "Security" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", - "guid": "7242c1de-da37-27f3-1ddd-565ccccb8ece", - "id": "G01.02", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "Enabling MFA and CA lets you manage risks before you grant users access to your AVD environment. When deciding which users to grant access to, we recommend you also consider who the user is, how they sign in, and which device they're using. Additional details and configuration procedures are provided in the companion article. Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", + "guid": "916d697d-8ead-4ed2-9bdd-186f1ac252b9", + "id": "G04.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-mfa", "services": [ - "AVS", - "Storage", - "AzurePolicy" + "AVD", + "Entra" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale in operations planning", - "waf": "Performance" + "subcategory": "Microsoft Entra ID", + "text": "Evaluate the usage of Multi-Factor Authentication (MFA) and Conditional Access (CA) for AVD users", + "waf": "Security" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", - "guid": "3233e49e-62ce-97f3-8737-8230e771b694", - "id": "G01.03", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", + "category": "Security", + "checklist": "Azure Virtual Desktop Review", + "description": "If Zero Trust is a requirement, review the companion article in the 'More Info' column. It provides steps to apply the principles of Zero Trust to an Azure Virtual Desktop deployment.", + "guid": "221102d0-90af-49fc-b2b7-8d3fe397e43", + "id": "G05.01", + "link": "https://learn.microsoft.com/security/zero-trust/azure-infrastructure-avd", "services": [ - "AVS" + "AVD" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale serialized operations planning", - "waf": "Performance" + "subcategory": "Zero Trust", + "text": "Review and Apply Zero Trust principles and guidance", + "waf": "Security" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", - "guid": "68161d66-5707-319b-e77d-9217da892593", - "id": "G01.04", - "link": "Best practice (testing)", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "If used, make sure to check the list of best practices and recommendations described in the referenced article.", + "guid": "9164e990-9ae2-48c8-9c33-b6b7808bafe6", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files#best-practices-for-azure-virtual-desktop", "services": [ - "AVS" + "AVD", + "Storage" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale rd operations planning", + "subcategory": "Azure Files", + "text": "Check best-practices for Azure Files", "waf": "Performance" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Define and enforce scale in/out maximum limits for your environment in the automations", - "guid": "c32cb953-e860-f204-957a-c79d61202669", - "id": "G01.05", - "link": "Operational planning - understand workload requirements", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "SMB Multichannel enables clients to use multiple network connections that provide increased performance while lowering the cost of ownership. Increased performance is achieved through bandwidth aggregation over multiple NICs and utilizing Receive Side Scaling (RSS) support for NICs to distribute the IO load across multiple CPUs.", + "guid": "5784b6ca-5e9e-4bcf-8b54-c95459ea7369", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-smb-multichannel-performance", "services": [ - "AVS" + "AVD", + "Storage", + "Cost", + "ACR" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scale maximum operations planning", + "severity": "Low", + "subcategory": "Azure Files", + "text": "Enable SMB multichannel when using a premium file share to host FSLogix profile containers.", "waf": "Performance" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", - "guid": "7bd65a5e-7b5d-652d-dbea-fc6f73a42857", - "id": "G01.06", - "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-management-and-monitoring", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "If a second region is required for DR purposes verify NetApp availability in there as well.", + "guid": "4a359836-ee79-4d6c-9d3a-364a5b7abae3", + "id": "H02.01", + "link": "https://azure.microsoft.com/global-infrastructure/services/", "services": [ - "AVS", - "Monitor" + "AVD", + "Storage" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Monitor scaling operations ", - "waf": "Performance" + "subcategory": "Azure NetApp Files", + "text": "If NetApp Files storage is required, check storage service availability in your specific region.", + "waf": "Reliability" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Consider the use of Azure Private-Link when using other Azure Native Services", - "guid": "95e374af-8a2a-2672-7ab7-b4a1be43ada7", - "id": "G02.01", - "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "CA option is a recommended setting in the FSLogix scenario, as it enables a more resilient SMB session between the Session Host and NetApp Files.", + "guid": "a2661898-866a-4c8d-9d1f-8cfc86e88024", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/virtual-desktop/create-fslogix-profile-container", "services": [ - "PrivateLink", - "AVS" + "AVD", + "Storage" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Private link", - "waf": "Performance" + "subcategory": "Azure NetApp Files", + "text": "If NetApp Files storage is used enable CA (Continuous Availability) option to increase resiliency", + "waf": "Reliability" }, { - "category": "Other Services/Operations", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", - "guid": "71eff90d-5ad7-ac60-6244-2a6f7d3c51f2", - "id": "G02.02", - "link": "Best practice", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "An Active Directory Site should be created for the Azure virtual network environment where Azure NetApp Files (ANF) subnet will be created, and that site name should be specified in the ANF connection property when executing the join procedure as explained in the reference article.", + "guid": "6647e977-db49-48a8-bc35-743f17499d42", + "id": "H02.03", + "link": "https://docs.microsoft.com/azure/azure-netapp-files/create-active-directory-connections", "services": [ - "AVS" + "VNet", + "AVD", + "Storage" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Provisioning Vmware VLANs", - "waf": "Performance" + "severity": "High", + "subcategory": "Azure NetApp Files", + "text": "If Azure NetApp Files storage is used, check Active Directory Site name setting in the Active Directory Connection configuration", + "waf": "Reliability" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "In which region will AVS be deployed", - "guid": "04e3a2f9-83b7-968a-1044-2811811a924b", - "id": "H01.01", - "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Possible options: Standard HDD, Standard SSD, or Premium SSD. Ephemeral disks are not supported, Ultra-Disks not recommended. Recommended to evaluate Premium for OS disk if user density is not low, and if Cloud Cache will be used. ", + "guid": "3611c818-b0a0-4bc5-80e4-3a18a9cd289c", + "id": "H03.01", + "link": "https://docs.microsoft.com/azure/virtual-machines/disks-types", "services": [ - "AVS" + "AVD", + "Storage" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Region selected", - "waf": "Reliability" + "subcategory": "Capacity Planning", + "text": "Determine which type of managed disk will be used for the Session Hosts", + "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Are there regulatory or compliance policies in play", - "guid": "e52d1615-9cc6-565c-deb6-743ed7e90f4b", - "id": "H01.02", - "link": "Internal policy or regulatory compliance", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Possible options are: Azure NetApp Files, Azure Files, VM based File Server. File-server it is not recommended. Azure Files Premium typically a good starting point. NetApp usually required for large scale / high-performant environment. For a detailed comparison see the article in the 'More Info' column.", + "guid": "ed6b17db-8255-4462-b2ae-e4553afc8339", + "id": "H03.02", + "link": "https://docs.microsoft.com/azure/virtual-desktop/store-fslogix-profile", "services": [ - "AVS", - "AzurePolicy" + "AVD", + "VM", + "Storage" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Data residency compliant with selected regions", - "waf": "Reliability" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Determine which storage backend solution will be used for FSLogix Profiles", + "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Request through the support blade", - "guid": "92bd5ad6-441f-a983-7aa9-05dd669d760b", - "id": "H01.03", - "link": "https://learn.microsoft.com/azure/migrate/concepts-azure-vmware-solution-assessment-calculation", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Every Host Pool should use a separate set of storage accounts/volumes (at least one) and shares. Users should have a different profile for each Host Pool since settings and configurations are specific to each Host Pool. Additionally, accessing different Host Pools at the same time can cause errors on the shared user profile VHD/X. Usage of different storage accounts/volumes for multiple shares is also recommended to scale independently.", + "guid": "2fad62bd-5004-453c-ace4-64d862e7f5a4", + "id": "H03.03", + "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", "services": [ - "AVS" + "AVD", + "Storage" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Request for number of AVS hosts submitted ", - "waf": "Reliability" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Do not share storage and profiles between different Host Pools", + "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "PG approval for deployment", - "guid": "28370f63-1cb8-2e35-907f-c5516b6954fa", - "id": "H01.04", - "link": "Support request through portal or get help from Account Team", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "As a starting point for estimating profile container storage performance requirements we recommend to assume 10 IOPS per user in the steady state and 50 IOPS per user during sign-in/sign-out. Space requirements is simply obtained based on the maximum profiles size in FSLogix per the total number of users for each Host Pool. Multiple storage accounts can be used for the same Host Pool if required.", + "guid": "680e7828-9c93-4665-9d02-bff4564b0d93", + "id": "H03.04", + "link": "https://learn.microsoft.com/azure/virtual-desktop/faq#what-s-the-largest-profile-size-fslogix-can-handle-", "services": [ - "AVS" + "AVD", + "Storage" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Region and number of AVS nodes approved", + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Verify storage scalability limits and Host Pool requirements", "waf": "Reliability" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Portal/subscription/resource providers/ Microsoft.AVS", - "guid": "96c76997-30a6-bb92-024d-f4f93f5f57fa", - "id": "H01.05", - "link": "Done through the subscription/resource providers/ AVS register in the portal", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Avoid introducing additional latency and costs associated with cross-region network traffic where possible.", + "guid": "8aad53cc-79e2-4e86-9673-57c549675c5e", + "id": "H03.05", + "link": "https://docs.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files", "services": [ - "Subscriptions", - "AVS" + "AVD", + "Storage", + "Cost" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Resource provider for AVS registered", - "waf": "Reliability" + "severity": "High", + "subcategory": "Capacity Planning", + "text": "For optimal performance, the storage solution and the FSLogix profile container should be in the same Azure region.", + "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Connectivity, subscription & governanace model", - "guid": "5898e3ff-5e6b-bee1-6f85-22fee261ce63", - "id": "H01.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/enterprise-scale-landing-zone", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "The recommendation in Azure Virtual Desktop is to use Profile Container without Office Container (ODFC) split unless you are planning for specific Business Continuity and Disaster Recovery (BCDR) scenarios as described in the Disaster Recovery section below. https://docs.microsoft.com/fslogix/profile-container-office-container-cncpt ", + "guid": "df47d2d9-2881-4b1c-b5d1-e54a29759e39", + "id": "H04.01", + "link": "https://learn.microsoft.com/fslogix/concepts-container-types#when-to-use-profile-and-odfc-containers", "services": [ - "Subscriptions", - "AVS" + "AVD", + "Storage", + "ASR" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Landing zone architecture", + "severity": "High", + "subcategory": "FSLogix", + "text": "Do not use Office Containers (ODFC) if not strictly required and justified", "waf": "Reliability" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "The name of the RG where AVS will exist", - "guid": "d0181fb8-9cb8-bf4b-f5e5-b5f9bf7ae4ea", - "id": "H01.07", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Make sure to configure the following antivirus exclusions for FSLogix Profile Container virtual hard drives, as documented in the referenced article in the 'More Info' column.", + "guid": "83f63047-22ee-479d-9b5c-3632054b69ba", + "id": "H04.02", + "link": "https://learn.microsoft.com/fslogix/overview-prerequisites#configure-antivirus-file-and-folder-exclusions", "services": [ - "AVS" + "AVD", + "Storage" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Resource group name selected", - "waf": "Reliability" + "subcategory": "FSLogix", + "text": "Configure the recommended antivirus exclusions for FSLogix (includes not scanning VHD(x) files on connect).", + "waf": "Security" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Each resource created as part of the deployment will also utilize this prefix in the name", - "guid": "0f0d20c2-5a19-726c-de20-0984e070d9d6", - "id": "H01.08", - "link": "Best practice - naming standards", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Profile containers have a default max size of 30GB. If large Profile Containers are anticipated, and customers wants to try to keep them small, consider using OneDrive to host Office 365 files outside the FSLogix profile.", + "guid": "01e6a84d-e5df-443d-8992-481718d5d1e5", + "id": "H04.03", + "link": "https://docs.microsoft.com/fslogix/profile-container-configuration-reference", "services": [ - "AVS" + "AVD", + "Storage" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Deployment prefix selected", - "waf": "Reliability" + "severity": "High", + "subcategory": "FSLogix", + "text": "Review and confirm configured maximum profile size in FSLogix", + "waf": "Cost" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "/22 unique non-overlapping IPv4 address space", - "guid": "7fbf2ab7-a36c-5957-c27a-67038557af2a", - "id": "H01.09", - "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-network-checklist#routing-and-subnet-considerations", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Defaults and recommended settings are reported in the companion article in the 'More Info' column. If not recommended keys and/or values must be used, be sure to review with a Microsoft AVD expert and clearly document your choices.", + "guid": "d34aad5e-8c78-4e1d-9666-7313c405674c", + "id": "H04.04", + "link": "https://learn.microsoft.com/fslogix/concepts-configuration-examples", "services": [ - "AVS" + "AVD", + "AKV", + "Storage", + "ACR" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Network space for AVS management layer", + "severity": "High", + "subcategory": "FSLogix", + "text": "Review FSLogix registry keys and determine which ones to apply", "waf": "Reliability" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "vNets used by workloads running in AVS (non-stretched)", - "guid": "0c87f999-e517-21ef-f355-f210ad4134d2", - "id": "H01.10", - "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/installation/GUID-4B3860B8-1883-48CA-B2F3-7C2205D91D6D.html", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Concurrent or multiple connections are not recommended in Azure Virtual Desktop. Concurrent connections are also not supported by Session Hosts running in an Azure Virtual Desktop Host Pool. OneDrive, if used, doesn't support concurrent or multiple connections using the same container, under any circumstance. For multiple connections, usage of the same profile disk is not recommended.", + "guid": "5e985b85-9c77-43e7-b261-623b775a917e", + "id": "H04.05", + "link": "https://learn.microsoft.com/fslogix/concepts-multi-concurrent-connections", "services": [ - "VNet", - "AVS" + "AVD", + "Storage" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Network space for AVS NSX-T segments", + "severity": "High", + "subcategory": "FSLogix", + "text": "Avoid usage of concurrent or multiple connections", "waf": "Reliability" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Choose AV36, AV36P, AV52, AV36T (AV36T = Trial)", - "guid": "946c8966-f902-6f53-4f37-00847e8895c2", - "id": "H01.11", - "link": "https://azure.microsoft.com/pricing/details/azure-vmware/", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "Cloud Cache uses OS drive as local cache storage and may generate lot of pressure on the VM disk. Depending on the VM SKU and size used, the VM temporary drive can be a viable and performant solution where to relocate Cloud Cache cached content. Before adopting this solution, tests should be executed to confirm performance and stability. More details on Cloud Cache can be found here: https://learn.microsoft.com/fslogix/concepts-fslogix-cloud-cache. ", + "guid": "b2d1215a-e114-4ba3-9df5-85ecdcd9bd3b", + "id": "H04.06", + "link": "https://docs.microsoft.com/fslogix/cloud-cache-configuration-reference", "services": [ - "AVS" + "AVD", + "VM", + "Storage" ], - "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "AVS SKU (region dependent)", + "severity": "Low", + "subcategory": "FSLogix", + "text": "If FSLogix Cloud Cache is used, consider moving the cache directory to the VM temporary drive.", "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use the Azure migration assessment tool to determine the minimum number of nodes required (consider BCDR as well)", - "guid": "31833808-26ba-9c31-416f-d54a89a17f5d", - "id": "H01.12", - "link": "https://learn.microsoft.com/azure/migrate/how-to-assess", + "category": "Storage", + "checklist": "Azure Virtual Desktop Review", + "description": "REDIRECTION.XML file is used to control what folders are redirected out of the profile container to the 'C:' drive. Exclusions should be the exception and should never be used unless the specific exclusion is completely understood by the person configuring the exclusion. Exclusions should always be fully tested in the environment where they are intended to be implemented. Configuring exclusions may impact functionality, stability and performance.", + "guid": "0b50ca97-b1d2-473c-b4d9-6e98b0f912de", + "id": "H04.07", + "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt#redirectionsxml", "services": [ - "AVS" + "AVD", + "Storage" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Number of hosts to be deployed", - "waf": "Performance" + "subcategory": "FSLogix", + "text": "Review the usage of FSLogix redirection.", + "waf": "Cost" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Understand how and if you should be using reserved instances (cost control)", - "guid": "f2b73c4f-3d46-32c9-5df1-5b8dfcd3947f", - "id": "H01.13", - "link": "https://azure.microsoft.com/en-ca/pricing/details/azure-vmware/#:~:text=Azure%20VMware%20Solution%20%20%20%20Instance%20size,TB%20%28all%20NVMe%29%20%20%20N%2FA%20%2Fhour%20", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "9f519499-5820-4060-88fe-cab4538c9dd0", + "id": "01.01.01", + "link": "https://learn.microsoft.com/windows-server/storage/storage-spaces/storage-spaces-direct-hardware-requirements", "services": [ - "AVS", - "Cost" + "Storage" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Reserverd Instances", - "waf": "Cost" + "subcategory": "Physical", + "text": "All planned storage pools should use direct-attached storage (SATA, SAS, NVMe)", + "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", - "guid": "94ac48ab-ade5-3fa7-f800-263feeb97070", - "id": "H01.14", - "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "f7c015e0-7d97-4283-b006-567afeb2b5ca", + "id": "01.01.02", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/drive-symmetry-considerations#understand-capacity-imbalance", "services": [ - "AVS", - "ASR" + "Storage", + "ACR" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Capacity ", + "subcategory": "Physical", + "text": "Disks are symmetrical across all nodes", "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Identify which of the networking scenarios make ", - "guid": "1f9d4bd5-14b8-928c-b4cb-eb211f9b8de5", - "id": "H01.15", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "f785b143-2c1e-4466-9baa-dde8ba4c7aaa", + "id": "01.02.01", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/fault-tolerance#parity", "services": [ - "AVS" + "Storage", + "Backup" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "Networking & Connectivity See docs describing scenrario 1 through 5", - "waf": "Reliability" + "subcategory": "S2D", + "text": "Parity type disk redundancy should only be used for low I/O volumes (backup/archive)", + "waf": "Performance" }, { - "category": "Planning", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", - "guid": "070db19b-8a2a-fd6a-c39b-4488d8780da9", - "id": "H01.16", - "link": "Please Check Partner Ecosystem", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "8a705965-9840-43cc-93b3-06d089406bb4", + "id": "01.02.02", + "link": "https://learn.microsoft.com/windows-server/storage/storage-spaces/storage-spaces-direct-hardware-requirements#physical-deployments", "services": [ - "AVS" + "Storage" ], "severity": "Medium", - "subcategory": "Pre-deployment", - "text": "3rd party application compatibility ", + "subcategory": "S2D", + "text": "Ensure there at least 2 capacity disks with available capacity in the Storage Pool", "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", - "guid": "70cfbddc-d3d4-9188-77c8-1cabaefef646", - "id": "I01.01", - "link": "General recommendation for storing encryption keys.", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "2a4f629a-d623-4610-a8e3-d6fd66057d8e", + "id": "01.02.03", + "link": "https://learn.microsoft.com/windows-server/storage/storage-spaces/delimit-volume-allocation", "services": [ - "AVS", - "AKV" + "Storage" ], - "severity": "Medium", - "subcategory": "Encryption", - "text": "Use Azure Key Vault with in-guest encryption ", - "waf": "Security" + "severity": "Low", + "subcategory": "S2D", + "text": "'Delimited allocation' has been considered to improve volume resiliency in a multi-node failure", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", - "guid": "c1a81638-18df-0ce9-a73a-4b9a8a8dd392", - "id": "I01.02", - "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#data-at-rest-encryption", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "960eb9be-1f0f-4fc1-9b31-fcf1cf9e34e6", + "id": "01.02.04", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/plan-volumes#choosing-how-many-volumes-to-create", "services": [ - "SQL", - "AVS" + "Storage" ], "severity": "Medium", - "subcategory": "Encryption", - "text": "Use in-guest encryption", - "waf": "Security" + "subcategory": "S2D", + "text": "CSVs are created in multiples of node count", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", - "guid": "8d0a8f51-8d35-19cd-c2fe-4e3512fb467e", - "id": "I01.03", - "link": "https://docs.microsoft.com/azure/key-vault/general/authentication", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "859ba2b9-a3a8-4ca1-bb61-165effbf1c03", + "id": "01.02.05", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/cache", "services": [ - "AVS", - "ExpressRoute", - "AKV" + "Storage" ], "severity": "Medium", - "subcategory": "Encryption", - "text": "Keyvault use for secrets", - "waf": "Security" + "subcategory": "S2D", + "text": "If a cache tier is implemented, the number of capacity drives is a multiple of the number of cache drives", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Older OS security patching configured for workloads running on Azure VMware Solution are eligible for ESU", - "guid": "4f8b20e9-a2a1-f80f-af9b-8aa3b26dca08", - "id": "I02.01", - "link": "https://docs.microsoft.com/windows-server/get-started/extended-security-updates-deploy", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "d8a65f05-db06-461d-81dc-7899ad3f8f1e", + "id": "01.02.06", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/plan-volumes#reserve-capacity", "services": [ - "AVS" + "Storage" ], "severity": "Medium", - "subcategory": "Extended support", - "text": "Ensure extended security update support ", - "waf": "Security" + "subcategory": "S2D", + "text": "A minimum of 1 type of each disk type per node has been factored as a reserve disk", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Use a SIEM/SOAR", - "guid": "9bb22fec-4d00-3b95-7136-e225d0f5c63a", - "id": "I03.01", - "link": "https://learn.microsoft.com/azure/sentinel/overview", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "description": "VMFleet is a tool that can be used to measure the performance of a storage subsystem, best used to baseline performance prior to workload deployment", + "guid": "9d138f1d-5363-476e-bbd7-acfa500bdc0c", + "id": "01.02.07", + "link": "https://github.com/microsoft/diskspd/wiki/VMFleet", "services": [ - "AVS", - "Sentinel" + "Storage" ], - "severity": "Medium", - "subcategory": "Investigation", - "text": "Enable Azure Sentinel or 3rd party SIEM ", - "waf": "Security" + "severity": "Low", + "subcategory": "S2D", + "text": "VMFleet has been run prior to workload deployment to baseline storage performance", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "MS Defender For Cloud, for workloads running on Azure VMware Solution", - "guid": "f42b0b09-c591-238a-1580-2de3c485ebd2", - "id": "I04.01", - "link": "https://learn.microsoft.com/azure/azure-vmware/azure-security-integration#prerequisites", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "13c12e2a-c938-4dd1-9223-507d5e17f9c5", + "id": "01.03.01", "services": [ - "AVS", - "Defender" + "Storage" ], "severity": "Medium", - "subcategory": "Security", - "text": "Enable Advanced Threat Detection ", - "waf": "Security" + "subcategory": "Host OS", + "text": "OS drives use a dedicated storage controller", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Are the applicable policies enabled (compliance baselines added to MDfC)", - "guid": "bcdd2348-3d0e-c6bb-1092-aa4cd1a66d6b", - "id": "I04.02", - "link": "https://docs.microsoft.com/azure/azure-vmware/azure-security-integration", + "category": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "a631e7dc-8879-45bd-b0a7-e5927b805428", + "id": "01.03.02", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/use-csv-cache", "services": [ - "AVS", - "AzurePolicy" + "Storage" ], "severity": "Medium", - "subcategory": "Security", - "text": "Policy & Regulatory Compliance", - "waf": "Security" + "subcategory": "Host OS", + "text": "CSV in-memory read caching is enabled and properly configured", + "waf": "Performance" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Azure to Azure (E/W), Azure to On-premises), AVS to Internet, AVS to Azure", - "guid": "607c1ca9-da92-ae19-5a4c-eb1e876acbe7", - "id": "J01.01", - "link": "https://techcommunity.microsoft.com/t5/azure-migration-and/firewall-integration-in-azure-vmware-solution/ba-p/2254961#:~:text=Azure%20VMware%20Solution%20customers%20have%20multiple%20security%20options,the%20box%20to%20provide%20East-West%20and%20North-South%20firewalling.", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "c062cd9a-f1db-4f83-aab3-9cb03f56c140", + "id": "02.01.01", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/host-network-requirements#switch-embedded-teaming-set", "services": [ - "AVS" + "ACR" ], "severity": "Medium", - "subcategory": "Firewalls", - "text": "Azure / 3rd party firewall", - "waf": "Security" + "subcategory": "Host", + "text": "NICs are symmetrical across nodes", + "waf": "Reliability" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "To allow HCX appliance to connect/sync", - "guid": "1d87925c-c02b-7fde-a425-7e95ad846a27", - "id": "J01.02", - "link": "https://docs.vmware.com/en/VMware-Cloud-on-AWS/services/com.vmware.vmc-aws-networking-security/GUID-2CFE1654-9CC9-4EDB-A625-21317299E559.html", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "ea8054db-a558-4533-80c8-5d9cf447ba19", + "id": "02.01.02", "services": [ - "AVS" + "Storage" ], - "severity": "Medium", - "subcategory": "Firewalls", - "text": "Firewalls allow for East/West traffic inside AVS", - "waf": "Security" + "severity": "High", + "subcategory": "Host", + "text": "Storage networking is redundant", + "waf": "Reliability" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Decision on which tool to use (SRM requires additional license - enables automation & other features)", - "guid": "468b3495-2f6e-b65a-38ef-3ba631bcaa46", - "id": "J02.01", - "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-B842696B-89EF-4183-9C73-B77157F56055.html", - "services": [ - "AVS" - ], + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "15d976c5-e267-49a1-8b00-62010bfa5188", + "id": "02.01.03", + "link": "https://learn.microsoft.com/azure-stack/hci/deploy/network-atc", + "services": [], "severity": "Medium", - "subcategory": "Networking", - "text": "HCX and/or SRM", + "subcategory": "Host", + "text": "Host networking configuration is managed by Network ATC and intents are healthy", "waf": "Reliability" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Read up on requirements for Service Mesh requirements and how HCX ", - "guid": "be2ced52-da08-d366-cf7c-044c19e29509", - "id": "J02.02", - "link": "https://docs.vmware.com/en/VMware-HCX/4.6/hcx-user-guide/GUID-76BCD059-A31A-4041-9105-ACFB56213E7C.html", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "676c53ad-b29a-4de1-9d03-d7d2674405b8", + "id": "02.01.04", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/network-hud-overview", + "services": [], + "severity": "Low", + "subcategory": "Host", + "text": "Network HUD has been configured", + "waf": "Reliability" + }, + { + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "8f6d58d9-6c1a-4ec1-b2d7-b2c6ba8f3949", + "id": "02.01.05", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/host-network-requirements", "services": [ - "AVS" + "Storage", + "VNet" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Configuring and Managing the HCX Interconnect", + "subcategory": "Host", + "text": "Storage NICs are assigned static IP addresses on separate subnets and VLANs", "waf": "Reliability" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "If you are planning on using stretch networks ensure that your on-premises environment requirements", - "guid": "7dcac579-fc5c-5c9c-f1f7-9b1149ff2c37", - "id": "J02.03", - "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-DBDB4D1B-60B6-4D16-936B-4AC632606909.html", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "824e53ec-953e-40c2-a6b8-52970b5b0f74", + "id": "02.01.06", + "link": "https://learn.microsoft.com/azure-stack/hci/plan/two-node-switched-converged", + "services": [], + "severity": "Medium", + "subcategory": "Host", + "text": "For switchless designs, dual link full mesh connectivity has been implemented", + "waf": "Reliability" + }, + { + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "dbc85d0e-0ebd-4589-a789-0fa8ceb1d0f0", + "id": "02.01.07", + "link": "https://learn.microsoft.com/azure-stack/hci/concepts/physical-network-requirements#using-switchless", "services": [ - "AVS" + "Storage" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Restrictions and limitations for network extensions", - "waf": "Performance" + "subcategory": "Host", + "text": "If the cluster is made up of more than 3 nodes, a switched storage network has been implemented", + "waf": "Reliability" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Do workloads require MoN?", - "guid": "cf45c0b9-6c4b-3bfb-86c5-62fe54061c73", - "id": "J02.04", - "link": "https://learn.microsoft.com/azure/azure-vmware/vmware-hcx-mon-guidance", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "603c6d71-59d2-419c-a312-8edc6e799c6a", + "id": "02.01.08", "services": [ - "AVS" + "Storage" ], + "severity": "High", + "subcategory": "Host", + "text": "RDMA is enabled on the Storage networking", + "waf": "Performance" + }, + { + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "9e260eae-bca1-4827-a259-76ee63fda8d6", + "id": "02.01.09", + "link": "https://github.com/microsoft/SDN/blob/master/Diagnostics/Test-Rdma.ps1", + "services": [], "severity": "Medium", - "subcategory": "Networking", - "text": "Mobility optimized networking", + "subcategory": "Host", + "text": "Test-RDMA.ps1 has been run to validate the RDMA configuration", "waf": "Performance" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Operating system level of Vmware environment", - "guid": "b7cf11f3-b12e-5189-991a-06df5250d2ca", - "id": "J03.01", - "link": "https://learn.microsoft.com/azure/site-recovery/vmware-physical-azure-support-matrix", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "description": "This ensures that Management traffic is not exposed to the VM traffic", + "guid": "abc85d0e-0ebd-4589-a777-0fa8ceb1d0f0", + "id": "02.01.10", + "link": "", "services": [ - "AVS" + "VM" ], "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Support matrix (OS versions etc).", - "waf": "Operations" + "subcategory": "Host", + "text": "If a VMSwitch is shared for Compute and Management traffic, require that Management traffic is tagged with a VLAN ID", + "waf": "Security" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Required that all switches are dynamic", - "guid": "45fe9252-aa1b-4e30-45c6-bc02f3b76acf", - "id": "J03.02", - "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/vsan-network-design-guide/GUID-91E1CD6F-33A6-4AC6-BC22-3E4807296F86.html#:~:text=Migrate%20Management%20Network%201%20Add%20hosts%20to%20the,each%20host.%20...%204%20Finish%20the%20configuration.%20", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "description": "This ensures you have at least 3 NCs active at all times during NC upgrades.", + "guid": "eb36f5f4-0fa7-4a2c-85f3-1b1c7c7817c0", + "id": "02.02.01", "services": [ - "AVS" + "VM" ], "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Standard switches converted to dynamic switches", - "waf": "Operations" + "subcategory": "SDN", + "text": "There are at least 3 Network Controller VMs deployed", + "waf": "Reliability" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "See sections on sizing and capacity in the link.", - "guid": "e9f6d736-ee44-e2ac-e7f9-e361f8c857f3", - "id": "J03.03", - "link": "https://learn.microsoft.com/azure/azure-vmware/plan-private-cloud-deployment", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "8bc78c85-6028-4a43-af2d-082a0a344909", + "id": "02.02.02", + "link": "https://learn.microsoft.com/windows-server/networking/sdn/manage/update-backup-restore", "services": [ - "AVS" + "Backup" ], - "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Capacity for HCX appliance", - "waf": "Performance" + "severity": "High", + "subcategory": "SDN", + "text": "Backups of SDN infrastructure are configured and tested", + "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Check hardware restrictions to ensure compatibility with AVS/OS ", - "guid": "1be2cdd6-15a7-9a33-aea7-113859035ce9", - "id": "J03.04", - "link": "https://kb.vmware.com/s/article/2007240#:~:text=ESXi%2FESX%20hosts%20and%20compatible%20virtual%20machine%20hardware%20versions,%20Not%20Supported%20%204%20more%20rows", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "51eaa4b6-b9a7-43e1-a7dc-634d3107bc6d", + "id": "03.01.01", "services": [ - "AVS" + "Monitor" ], "severity": "Medium", - "subcategory": "On-premises pre-requisites", - "text": "Hardware compatibility", + "subcategory": "Cluster", + "text": "SCOM Managed Instance has been considered for more complex monitoring and alerting scenarios", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Need to be converted", - "guid": "16ab821a-27c6-b6d3-6042-10dc4d6dfcb7", - "id": "J04.01", - "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.storage.doc/GUID-01D3CF47-A84A-4988-8103-A0487D6441AA.html", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "831f5aca-99ef-41e7-8263-9509f5093b43", + "id": "03.01.02", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/setup-hci-system-alerts", "services": [ - "AVS", - "Storage" + "Monitor" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "VSAN RDM disks are converted - not supported.", + "severity": "High", + "subcategory": "Cluster", + "text": "Alerts have been configured for the cluster, either using Azure Monitor, SCOM, or a third-party solution", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Need to be converted", - "guid": "eb2f9313-afb2-ab35-aa24-6d97a3cb0611", - "id": "J04.02", - "link": "3rd-Party tools", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "f95d0e7e-9f61-476d-bf65-59f2454d1d39", + "id": "03.01.03", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/monitor-hci-single?tabs=22h2-and-later", "services": [ - "VM", - "AVS", - "Storage" + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "VM with SCSI shared bus are not supported", + "subcategory": "Cluster", + "text": "Insights has been enabled at the cluster level and all nodes are reporting data", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Remove Direct IO before migration", - "guid": "3f2a5cff-c8a6-634a-1f1b-53ef9d321381", - "id": "J04.03", - "link": "Contact VMware", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "f4250fcb-ff53-40c9-b304-3560464fd90c", + "id": "03.01.04", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/monitor-hci-single?tabs=22h2-and-later", "services": [ - "VM", - "AVS", - "Storage" + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "VM with Direct IO require removing DirectPath device", + "subcategory": "Cluster", + "text": "Azure Monitoring Agent has been deployed to hosts and an appropriate Data Collection Rule has been configured", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Cannot migrate clusters ", - "guid": "efc8a311-74f8-0252-c6a0-4bac7610e266", - "id": "J04.04", - "link": "Contact VMware", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "6143af1d-0d1a-4163-b1c9-662f7459bb98", + "id": "03.02.01", "services": [ - "AVS", - "Storage" + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Shared VMDK files are not supported", + "subcategory": "Hardware", + "text": "Relevant hardware monitoring has been configured", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Convert to a different format", - "guid": "ab6c89cd-a26f-b894-fe59-61863975458e", - "id": "J04.05", - "link": "Contact VMware", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "9cbdf225-549a-41cf-9c97-794766a6f2b0", + "id": "03.02.02", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/health-service-overview", "services": [ - "AVS", - "Storage" + "Monitor" ], "severity": "Medium", - "subcategory": "Storage", - "text": "RDM with 'physical compatibility mode' are not supported.", + "subcategory": "Hardware", + "text": "Relevant hardware alerting has been configured", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning 'RAID-1 FTT-1' is default with Thin Provisioning", - "guid": "7628d446-6b10-9678-9cec-f407d990de43", - "id": "J04.06", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "c0da5bbd-0f0d-4a26-98ec-38c9cc42b323", + "id": "04.01.01", "services": [ - "VM", - "AVS", - "Storage", - "AzurePolicy" + "VM" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Default storage policy", + "severity": "Low", + "subcategory": "VM Management - Resource Bridge", + "text": "The Azure CLI has been installed on every node to enable RB management from WAC", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "The default storage policy is set to RAID-1 (Mirroring) FTT-1, with Object Space Reservation set to Thin provisioning.", - "guid": "37fef358-7ab9-43a9-542c-22673955200e", - "id": "J04.07", - "link": "https://learn.microsoft.com/azure/azure-vmware/configure-storage-policy", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "a8ecf23c-c048-4fa9-b87b-51ebfb409863", + "id": "04.01.02", "services": [ - "VM", - "AVS", - "Storage", - "AzurePolicy" + "VM" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Ensure that the appropriate VM template storage policy is used", + "severity": "Low", + "subcategory": "VM Management - Resource Bridge", + "text": "DHCP is available in the cluster to support Guest Configuration at VM deployment from Azure", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", - "guid": "ebebd109-9f9d-d85e-1b2f-d302012843b7", - "id": "J04.08", - "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "category": "Backup and Disaster Recovery", + "checklist": "Azure Stack HCI Review", + "guid": "074541e3-fe08-458a-8062-32d13dcc10c6", + "id": "05.01.01", + "link": "https://learn.microsoft.com/azure/backup/back-up-azure-stack-hyperconverged-infrastructure-virtual-machines", "services": [ - "AVS", - "Storage", - "AzurePolicy" + "ASR", + "VM", + "Backup" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Failure to tolerate policy", + "severity": "High", + "subcategory": "VM", + "text": "Backups of HCI VMs have been configured using MABS or a third-party solution", "waf": "Operations" }, { - "category": "VMware", - "checklist": "Azure VMware Solution Implementation Checklist", - "description": "ANF can be used to extend storage for Azure VMware Solution,", - "guid": "1be821bd-4f37-216a-3e3d-2a5ac6996863", - "id": "J04.09", - "link": "https://learn.microsoft.com/azure/azure-vmware/netapp-files-with-azure-vmware-solution", - "services": [ - "AVS", - "Storage" - ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Use ANF for external storage", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "48f7ae57-1035-4101-8a38-fbe163d03e8a", + "id": "06.01.01", + "services": [], + "severity": "High", + "subcategory": "Cluster Configuration", + "text": "Cluster configuration or a configuration script has been documented and maintained", "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable image export to prevent data exfiltration. Note that this will prevent image import of images into another ACR instance.", - "guid": "ab91932c-9fc9-4d1b-a880-37f5e6bfcb9e", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/container-registry/data-loss-prevention", - "services": [ - "ACR" - ], + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "f2a6a19a-ffe6-444d-badb-cb336c8e7b50", + "id": "06.01.02", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/witness", + "services": [], "severity": "High", - "subcategory": "Data Protection", - "text": "Disable Azure Container Registry image export", - "waf": "Security" + "subcategory": "Cluster Configuration", + "text": "A cluster witness has been configured for clusters with less than 5 nodes", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Enable audit compliance visibility by enabling Azure Policy for Azure Container Registry", - "guid": "d503547c-d447-4e82-9128-a7100f1cac6d", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-azure-policy", - "services": [ - "ACR", - "AzurePolicy" - ], + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "a47339fe-62c5-44a0-bb83-3d46ef16292f", + "id": "06.01.03", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/update-cluster", + "services": [], + "severity": "Medium", + "subcategory": "Cluster Configuration", + "text": "Cluster-Aware Updating has been configured for Windows and hardware updates (if available)", + "waf": "Operations" + }, + { + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "7f1d6fe8-3079-44ea-8ea6-14494d1aa470", + "id": "06.01.04", + "link": "https://learn.microsoft.com/azure-stack/hci/deploy/validate", + "services": [], "severity": "High", - "subcategory": "Data Protection", - "text": "Enable Azure Policies for Azure Container Registry", - "waf": "Security" + "subcategory": "Cluster Configuration", + "text": "Cluster validation has been run against the configured cluster", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "The Azure Key Vault (AKV) is used to store a signing key that can be utilized by?notation?with the notation AKV plugin (azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach these signatures using the?az?or?oras?CLI commands.", - "guid": "d345293c-7639-4637-a551-c5c04e401955", - "id": "A01.03", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-tutorial-sign-build-push", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "81693af0-5638-4aa2-a153-1d6189df30a7", + "id": "06.01.05", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/azure-benefits", "services": [ - "ACR", - "AKV" + "VM" ], - "severity": "High", - "subcategory": "Data Protection", - "text": "Sign and Verify containers with notation (Notary v2)", - "waf": "Security" + "severity": "Medium", + "subcategory": "Cluster Configuration", + "text": "Azure Benefits has been enabled at the cluster and VM levels", + "waf": "Cost" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Azure Container Registry automatically encrypts images and other artifacts that you store. By default, Azure automatically encrypts the registry content at rest by using service-managed keys. By using a customer-managed key, you can supplement default encryption with an additional encryption layer.", - "guid": "0bd05dc2-efd5-4d76-8d41-d2500cc47b49", - "id": "A01.04", - "link": "https://learn.microsoft.com/azure/container-registry/tutorial-customer-managed-keys", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "8c967ee8-8170-4537-a28d-33431cd3632a", + "id": "06.01.06", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/use-environment-checker", + "services": [], + "severity": "Medium", + "subcategory": "Cluster Configuration", + "text": "The Environment Checker module has been run to validate the environment", + "waf": "Reliability" + }, + { + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "43ffbfab-766e-4950-a102-78b479136e4d", + "id": "06.02.01", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/azure-benefits", "services": [ - "ACR", - "AKV" + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Data Protection", - "text": "Encrypt registry with a customer managed key", - "waf": "Security" + "subcategory": "Cluster Configuration", + "text": "Group Policy inheritance on the HCI cluster and node Active Directory organizational unit has been blocked or applied policies have been evaluated for compatibility issues (usually WinRM and PowerShell execution policy)", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Use managed identities to secure ACRPull/Push RBAC access from client applications", - "guid": "8f42d78e-79dc-47b3-9bd2-a1a27e7a8e90", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "e6a3f3a7-4a7d-49e2-985a-6e39dd284027", + "id": "06.02.02", + "services": [], + "severity": "Medium", + "subcategory": "Cluster Configuration", + "text": "WAC is on the latest release and configured to automatically upgrade extensions", + "waf": "Reliability" + }, + { + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "d1caa31f-cc26-42b2-b92f-2b667c0e6020", + "id": "07.01.01", + "link": "https://learn.microsoft.com/azure/architecture/hybrid/azure-stack-hci-dr", "services": [ - "RBAC", - "ACR", "Entra" ], - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Use Managed Identities to connect instead of Service Principals", - "waf": "Security" + "severity": "Medium", + "subcategory": "Stretch Clustering", + "text": "There is sub 5ms latency between each site if synchronous replication is being configured AAD", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "The local Administrator account is disabled by default and should not be enabled. Use either Token or RBAC-based access methods instead", - "guid": "be0e38ce-e297-411b-b363-caaab79b198d", - "id": "A02.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "3277558e-3155-4088-b49a-78594cb4ce1a", + "id": "07.01.02", "services": [ - "RBAC", - "ACR", - "Entra" + "Storage", + "VNet" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable local authentication for management plane access", - "waf": "Security" + "subcategory": "Stretch Clustering", + "text": "Management, Replication and Storage networks excluded from stretched VLANs configurations, are routed, and in different subnets", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable Administrator account and assign RBAC roles to principals for ACR Pull/Push operations", - "guid": "387e5ced-126c-4d13-8af5-b20c6998a646", - "id": "A02.03", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-roles?tabs=azure-cli", - "services": [ - "RBAC", - "ACR", - "Entra" - ], + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "baed6066-8531-44ba-bd94-38cbabbf4099", + "id": "07.02.01", + "services": [], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Assign AcrPull & AcrPush RBAC roles rather than granting Administrative access to identity principals", - "waf": "Security" + "subcategory": "Stretch Clustering", + "text": "There is a plan detailed for site failure and recovery", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable anonymous pull/push access", - "guid": "e338997e-41c7-47d7-acf6-a62a1194956d", - "id": "A02.04", - "link": "https://learn.microsoft.com/azure/container-registry/anonymous-pull-access#configure-anonymous-pull-access", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b4", + "id": "07.02.02", "services": [ - "ACR", - "Entra" + "ACR" ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Disable Anonymous pull access", - "waf": "Security" + "subcategory": "Stretch Clustering", + "text": "Separate vLANs and networks are used for each replication network across both sites", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Token authentication doesn't support assignment to an AAD principal. Any tokens provided are able to be used by anyone who can access the token", - "guid": "698dc3a2-fd27-4b2e-8870-1a1252beedf6", - "id": "A02.05", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication?tabs=azure-cli", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b5", + "id": "07.02.03", + "link": "https://learn.microsoft.com/azure/architecture/hybrid/azure-stack-hci-dr#cost-optimization", "services": [ - "ACR", - "Entra" + "Storage" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable repository-scoped access tokens", - "waf": "Security" + "subcategory": "Stretch Clustering", + "text": "Use either a cloud witness or a file share witness in a third site for cluster quorum for clusters with less than 5 nodes", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Deploy container images to an ACR behind a Private endpoint within a trusted network", - "guid": "b3bec3d4-f343-47c1-936d-b55f27a71eee", - "id": "A02.06", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b6", + "id": "07.02.04", + "link": "https://learn.microsoft.com/azure/architecture/hybrid/azure-stack-hci-dr#cost-optimization", + "services": [], + "severity": "High", + "subcategory": "Stretch Clustering", + "text": "When using data deduplication, only enable it on the primary/source volumes", + "waf": "Reliability" + }, + { + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "ac527887-f6f4-40a3-b883-e04d704f013b", + "id": "07.02.04", + "link": "https://learn.microsoft.com/windows-server/storage/storage-replica/stretch-cluster-replication-using-shared-storage#provision-operating-system-features-roles-storage-and-network", "services": [ - "PrivateLink", - "EventHubs", - "ACR", - "Entra" + "Storage" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Deploy images from a trusted environment", - "waf": "Security" + "subcategory": "Stretch Clustering", + "text": "Storage backing log volumes must be faster (ideally) or at least as fast as capacity storage", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Only tokens with an ACR audience can be used for authentication. Used when enabling Conditional access policies for ACR", - "guid": "3a041fd3-2947-498b-8288-b3c6a56ceb54", - "id": "A02.07", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-enable-conditional-access-policy", + "category": "Backup and Disaster Recovery", + "checklist": "Azure Stack HCI Review", + "guid": "8ea49f70-1038-4283-b0c4-230165d3eabc", + "id": "08.01.01", + "link": "https://learn.microsoft.com/azure-stack/hci/manage/azure-site-recovery", "services": [ - "ACR", - "AzurePolicy", - "Entra" + "Backup", + "ASR" ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Disable Azure ARM audience tokens for authentication", - "waf": "Security" + "subcategory": "Disaster Recovery", + "text": "Azure Site Recovery has been considered for DR purposes", + "waf": "Operations" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Set up a diagnostic setting to send 'repositoryEvents' & 'LoginEvents' to Log Analytics as the central destination for logging and monitoring. This allows you to monitor control plane activity on the ACR resource itself.", - "guid": "8a488cde-c486-42bc-9bd2-1be77f26e5e6", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/container-registry/monitor-service", - "services": [ - "ACR", - "Entra", - "Monitor" - ], + "checklist": "Azure Stack HCI Review", + "guid": "03e65fdc-2628-4a1a-ba2e-a5174340ba52", + "id": "09.01.01", + "link": "https://learn.microsoft.com/windows/security/operating-system-security/data-protection/bitlocker/protecting-cluster-shared-volumes-and-storage-area-networks-with-bitlocker", + "services": [], "severity": "Medium", - "subcategory": "Logging and Monitoring", - "text": "Enable diagnostics logging", + "subcategory": "Host", + "text": "BitLocker has been enabled on CSVs for volume encryption, where appropriate", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Service supports disabling public network access either through using service-level IP ACL filtering rule (not NSG or Azure Firewall) or using a 'Disable Public Network Access' toggle switch", - "guid": "21d41d25-00b7-407a-b9ea-b40fd3290798", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", - "services": [ - "PrivateLink", - "Firewall", - "VNet", - "ACR" - ], + "checklist": "Azure Stack HCI Review", + "guid": "9645d2e6-ba28-453c-b6d5-d9ef29fc34be", + "id": "09.01.02", + "link": "https://learn.microsoft.com/windows-server/storage/file-server/smb-security", + "services": [], "severity": "Medium", - "subcategory": "Network Security", - "text": "Control inbound network access with Private Link", + "subcategory": "Host", + "text": "SMB encryption has been enabled, where appropriate", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable public network access if inbound network access is secured using Private Link", - "guid": "cd289ced-6b17-4db8-8554-62f2aee4553a", - "id": "A04.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-access-selected-networks#disable-public-network-access", + "checklist": "Azure Stack HCI Review", + "guid": "8f03437a-5068-4486-9a78-0402ce771298", + "id": "09.01.03", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/microsoft-defender-antivirus-on-windows-server", "services": [ - "PrivateLink", - "ACR" + "Defender" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Disable Public Network access", + "subcategory": "Host", + "text": "Microsoft Defender Antivirus has been enabled on all nodes", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Only the ACR Premium SKU supports Private Link access", - "guid": "fc833934-8b26-42d6-ac5f-512925498f6d", - "id": "A04.03", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-skus", - "services": [ - "PrivateLink", - "ACR" - ], + "checklist": "Azure Stack HCI Review", + "guid": "dba6b211-fc02-43b3-b7c8-f163c188332e", + "id": "09.01.04", + "link": "https://learn.microsoft.com/windows/security/identity-protection/credential-guard/credential-guard-manage", + "services": [], "severity": "Medium", - "subcategory": "Network Security", - "text": "Use an Azure Container Registry SKU that supports Private Link (Premium SKU)", + "subcategory": "Host", + "text": "Credential Guard has been configured, where appropriate", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Azure Defender for containers or equivalent service should be used to scan container images for vulnerabilities", - "guid": "bad37dac-43bc-46ce-8d7a-a9b24604489a", - "id": "A04.04", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", + "checklist": "Azure App Security Review", + "description": "Use Azure Key Vault to store any secrets the application needs. Key Vault provides a safe and audited environment for storing secrets and is well-integrated with App Service through the Key Vault SDK or App Service Key Vault References.", + "guid": "834ac932-223e-4ce8-8b12-3071a5416415", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", "services": [ - "ACR", - "Defender" + "AKV", + "AppSvc" ], - "severity": "Low", - "subcategory": "Network Security", - "text": "Enable Defender for Containers to scan Azure Container Registry for vulnerabilities", + "severity": "High", + "subcategory": "Data Protection", + "text": "Use Key Vault to store secrets", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", - "guid": "4451e1a2-d345-4293-a763-9637a551c5c0", - "id": "A05.01", + "checklist": "Azure App Security Review", + "description": "Use a Managed Identity to connect to Key Vault either using the Key Vault SDK or through App Service Key Vault References.", + "guid": "833ea3ad-2c2d-4e73-8165-c3acbef4abe1", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", "services": [ - "ACR" + "AKV", + "Entra", + "AppSvc" ], - "severity": "Medium", - "subcategory": "Vulnerability Management", - "text": "Deploy validated container images", + "severity": "High", + "subcategory": "Data Protection", + "text": "Use Managed Identity to connect to Key Vault", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", - "guid": "4e401955-387e-45ce-b126-cd132af5b20c", - "id": "A05.02", + "checklist": "Azure App Security Review", + "description": "Store the App Service TLS certificate in Key Vault.", + "guid": "f8d39fda-4776-4831-9c11-5775c2ea55b4", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-certificate", "services": [ - "ACR" + "AKV", + "AppSvc" ], "severity": "High", - "subcategory": "Vulnerability Management", - "text": "Use up-to-date platforms, languages, protocols and frameworks", + "subcategory": "Data Protection", + "text": "Use Key Vault to store TLS certificate.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hub provides encryption of data at rest. If you use your own key, the data is still encrypted using the Microsoft-managed key, but in addition the Microsoft-managed key will be encrypted using the customer-managed key. ", - "guid": "7aaf12e7-b94e-4f6e-847d-2d92981b1cd6", - "link": "https://learn.microsoft.com/azure/event-hubs/configure-customer-managed-key", + "checklist": "Azure App Security Review", + "description": "Systems that process sensitive information should be isolated. To do so, use separate App Service Plans or App Service Environments and consider the use of different subscriptions or management groups.", + "guid": "6ad48408-ee72-4734-a475-ba18fdbf590c", + "id": "A01.04", + "link": "https://learn.microsoft.com/azure/app-service/overview-hosting-plans", "services": [ - "EventHubs" - ], - "severity": "Low", - "subcategory": "Data Protection", - "text": "Use customer-managed key option in data at rest encryption when required", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" - }, - { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hubs namespaces permit clients to send and receive data with TLS 1.0 and above. To enforce stricter security measures, you can configure your Event Hubs namespace to require that clients send and receive data with a newer version of TLS. If an Event Hubs namespace requires a minimum version of TLS, then any requests made with an older version will fail. ", - "guid": "d2f54b29-769e-43a6-a0e7-828ac936657e", - "link": "https://learn.microsoft.com/azure/event-hubs/transport-layer-security-configure-minimum-version", - "services": [ - "EventHubs" + "Subscriptions", + "AppSvc" ], "severity": "Medium", "subcategory": "Data Protection", - "text": "Enforce a minimum required version of Transport Layer Security (TLS) for requests ", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" + "text": "Isolate systems that process sensitive information", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "When you create an Event Hubs namespace, a policy rule named RootManageSharedAccessKey is automatically created for the namespace. This policy has manage permissions for the entire namespace. It’s recommended that you treat this rule like an administrative root account and don’t use it in your application. Using AAD as an authentication provider with RBAC is recommended. ", - "guid": "13b0f566-4b1e-4944-a459-837ee79d6c6d", - "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature#shared-access-authorization-policies", + "checklist": "Azure App Security Review", + "description": "Local disks on App Service are not encrypted and sensitive data should not be stored on those. (For example: D:\\\\Local and %TMP%).", + "guid": "e65de8e0-3f9b-4cbd-9682-66abca264f9a", + "id": "A01.05", + "link": "https://learn.microsoft.com/azure/app-service/operating-system-functionality#file-access", "services": [ - "EventHubs", - "RBAC", - "Entra", "TrafficManager", - "AzurePolicy" + "AppSvc" ], "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Avoid using root account when it is not necessary", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" + "subcategory": "Data Protection", + "text": "Do not store sensitive data on local disk", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Managed identities for Azure resources can authorize access to Event Hubs resources using Azure AD credentials from applications running in Azure Virtual Machines (VMs), Function apps, Virtual Machine Scale Sets, and other services. By using managed identities for Azure resources together with Azure AD authentication, you can avoid storing credentials with your applications that run in the cloud. ", - "guid": "3a365a5c-7acb-4e48-abd5-4cd79f2e8776", - "link": "https://learn.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest", + "checklist": "Azure App Security Review", + "description": "For authenticated web application, use a well established Identity Provider like Azure AD or Azure AD B2C. Leverage the application framework of your choice to integrate with this provider or use the App Service Authentication / Authorization feature.", + "guid": "919ca0b2-c121-459e-814b-933df574eccc", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/app-service/overview-authentication-authorization", "services": [ - "VM", - "EventHubs", - "Storage", "Entra", - "AKV" + "AppSvc" ], "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "When possible, your application should be using a managed identity to authenticate to Azure Event Hub. If not, consider having the storage credential (SAS, service principal credential) in Azure Key Vault or an equivalent service", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "subcategory": "Identity and Access Control", + "text": "Use an established Identity Provider for authentication", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "When creating permissions, provide fine-grained control over a client's access to Azure Event Hub. Permissions in Azure Event Hub can and should be scoped to the individual resource level e.g. consumer group, event hub entity, event hub namespaces, etc.", - "guid": "8357c559-675c-45ee-a5b8-6ad8844ce3b2", - "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory#azure-built-in-roles-for-azure-event-hubs", + "checklist": "Azure App Security Review", + "description": "Deploy code to App Service from a controlled and trusted environment, like a well-managed and secured DevOps deployment pipeline. This avoids code that was not version controlled and verified to be deployed from a malicious host.", + "guid": "3f9bcbd4-6826-46ab-aa26-4f9a19aed9c5", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/app-service/deploy-best-practices", "services": [ - "EventHubs", - "RBAC", - "Entra" + "Entra", + "AppSvc" ], "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Use least privilege data plane RBAC", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" - }, - { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hub resource logs include operational logs, virtual network and Kafka logs. Runtime audit logs capture aggregated diagnostic information for all data plane access operations (such as send or receive events) in Event Hubs.", - "guid": "b38b875b-a1cf-4104-a900-3a4d3ce474db", - "link": "https://learn.microsoft.com/azure/event-hubs/monitor-event-hubs-reference", - "services": [ - "VNet", - "EventHubs", - "Monitor" - ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable logging for security investigation. Use Azure Monitor to captured metrics and logs such as resource logs, runtime audit logs and Kafka logs", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" - }, - { - "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "Azure Event Hub by default has a public IP address and is Internet-reachable. Private endpoints allow traffic between your virtual network and Azure Event Hub traverses over the Microsoft backbone network. In addition to that, you should disable public endpoints if those are not used. ", - "guid": "5abca2a4-eda1-4dae-8cc9-5d48c6b791dc", - "link": "https://learn.microsoft.com/azure/event-hubs/private-link-service", - "services": [ - "PrivateLink", - "EventHubs", - "VNet" - ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Consider using private endpoints to access Azure Event Hub and disable public network access when applicable.", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "subcategory": "Identity and Access Control", + "text": "Deploy from a trusted environment", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure Event Hub Review", - "description": "With IP firewall, you can restrict public endpoint further to only a set of IPv4 addresses or IPv4 address ranges in CIDR (Classless Inter-Domain Routing) notation. ", - "guid": "a0e6c465-89e5-458b-a37d-3974d1112dbd", - "link": "https://learn.microsoft.com/azure/event-hubs/event-hubs-ip-filtering", - "services": [ - "EventHubs" - ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Consider only allowing access to Azure Event Hub namespace from specific IP addresses or ranges", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" - }, - { - "category": "Identity and Access Management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "d7e47431-76c8-4bdb-b55b-ce619e8a03f9", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/openshift/howto-create-service-principal?pivots=aro-azurecli", + "checklist": "Azure App Security Review", + "description": "Disable basic authentication for both FTP/FTPS and for WebDeploy/SCM. This disables access to these services and enforces the use of Azure AD secured endpoints for deployment. Note that the SCM site can also be opened using Azure AD credentials.", + "guid": "5d04c2c3-919c-4a0b-8c12-159e114b933d", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/app-service/deploy-configure-credentials#disable-basic-authentication", "services": [ - "RBAC", "Entra" ], "severity": "High", - "subcategory": "Identity", - "text": "Create a service principal and its role assignments before creating the ARO clusters.", + "subcategory": "Identity and Access Control", + "text": "Disable basic authentication", "waf": "Security" }, { - "category": "Identity and Access Management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "7879424d-6267-486d-90b9-6c97be985190", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/openshift/configure-azure-ad-ui", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Where possible use Managed Identity to connect to Azure AD secured resources. If this is not possible, store secrets in Key Vault and connect to Key Vault using a Managed Identity instead.", + "guid": "f574eccc-d9bd-43ba-bcda-3b54eb2eb03d", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/app-service/overview-managed-identity?tabs=portal%2Chttp", "services": [ + "AKV", "Entra" ], "severity": "High", - "subcategory": "Identity", - "text": "Use AAD to authenticate users in your ARO cluster.", + "subcategory": "Identity and Access Control", + "text": "Use Managed Identity to connect to resources", "waf": "Security" }, { - "category": "Identity and Access Management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "483835c9-86bb-4291-8155-a11475e39f54", - "id": "A01.03", - "link": "https://docs.openshift.com/container-platform/4.13/applications/projects/working-with-projects.html", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Where using images stored in Azure Container Registry, pull these using a Managed Identity.", + "guid": "d9a25827-18d2-4ddb-8072-5769ee6691a4", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/app-service/configure-custom-container#use-managed-identity-to-pull-image-from-azure-container-registry", "services": [ - "RBAC", + "ACR", "Entra" ], "severity": "High", - "subcategory": "Identity", - "text": "Define OpenShift projects to restrict RBAC privilege and isolate workloads in your cluster.", + "subcategory": "Identity and Access Control", + "text": "Pull containers using a Managed Identity", "waf": "Security" }, { - "category": "Identity and Access Management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "0acccd97-9376-4bcd-a375-0ab2ab039da6", - "id": "A01.04", - "link": "https://docs.openshift.com/container-platform/4.13/authentication/using-rbac.html", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "By configuring the diagnostic settings of App Service, you can send all telemetry to Log Analytics as the central destination for logging and monitoring. This allows you to monitor runtime activity of App Service such as HTTP logs, application logs, platform logs, ...", + "guid": "47768314-c115-4775-a2ea-55b46ad48408", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs", "services": [ - "RBAC", - "Entra" + "Monitor", + "Entra", + "AppSvc" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Define the required RBAC roles in OpenShift are scoped to either a project or a cluster.", + "subcategory": "Logging and Monitoring", + "text": "Send App Service runtime logs to Log Analytics", "waf": "Security" }, { - "category": "Identity and Access Management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "d54d7c89-29db-4107-b532-5ae625ca44e4", - "id": "A01.05", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Set up a diagnostic setting to send the activity log to Log Analytics as the central destination for logging and monitoring. This allows you to monitor control plane activity on the App Service resource itself.", + "guid": "ee72734b-475b-4a18-bdbf-590ce65de8e0", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", "services": [ + "Monitor", "Entra", - "AKV" + "AppSvc" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Minimize the number of users who have administrator rights and secrets access.", + "subcategory": "Logging and Monitoring", + "text": "Send App Service activity logs to Log Analytics", "waf": "Security" }, { - "category": "Identity and Access Management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "685e2223-ace8-4bb1-8307-ca5f16f154e3", - "id": "A01.06", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Control outbound network access using a combination of regional VNet integration, network security groups and UDR's. Traffic should be routed to an NVA such as Azure Firewall. Ensure to monitor the Firewall's logs.", + "guid": "c12159e1-14b9-433d-b574-ecccd9bd3baf", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/app-service/overview-vnet-integration", "services": [ - "RBAC", - "Entra" + "Firewall", + "Monitor", + "VNet", + "NVA" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Use Privileged Identity Management in AAD for ARO users with privileged roles.", + "subcategory": "Network Security", + "text": "Outbound network access should be controlled", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "aa369282-9e7e-4216-8836-87af467a1f89", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "You can provide a stable outbound IP by using VNet integration and using a VNet NAT Gateway or an NVA like Azure Firewall. This allows the receiving party to allow-list based on IP, should that be needed. Note that for communications towards Azure Services often there's no need to depend on the IP address and mechanics like Service Endpoints should be used instead. (Also the use of private endpoints on the receiving end avoids for SNAT to happen and provides a stable outbound IP range.)", + "guid": "cda3b54e-b2eb-403d-b9a2-582718d2ddb1", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/app-service/networking/nat-gateway-integration", "services": [ "VNet", - "Firewall", - "Entra", - "DDoS", - "WAF", - "Subscriptions" + "Storage", + "PrivateLink", + "NVA", + "Firewall" ], "severity": "Low", - "subcategory": "DDoS", - "text": "Use Azure DDoS Network/IP Protection to protect the virtual network you use for the ARO cluster unless you use Azure Firewall or WAF in a centralized subscription", + "subcategory": "Network Security", + "text": "Ensure a stable IP for outbound communications towards internet addresses", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "35bda433-24f1-4481-8533-182aa5174269", - "id": "B02.01", - "link": "https://docs.openshift.com/container-platform/4.13/networking/routes/secured-routes.html", - "services": [], - "severity": "High", - "subcategory": "Encryption", - "text": "All web applications you configure to use an ingress should use TLS encryption and shouldn't allow access over unencrypted HTTP.", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Control inbound network access using a combination of App Service Access Restrictions, Service Endpoints or Private Endpoints. Different access restrictions can be required and configured for the web app itself and the SCM site.", + "guid": "0725769e-e669-41a4-a34a-c932223ece80", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/app-service/networking-features#access-restrictions", + "services": [ + "PrivateLink", + "AppSvc" + ], + "severity": "High", + "subcategory": "Network Security", + "text": "Inbound network access should be controlled", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "44008ae7-d7e4-4743-876c-8bdbf55bce61", - "id": "B03.01", - "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Protect against malicious inbound traffic using a Web Application Firewall like Application Gateway or Azure Front Door. Make sure to monitor the WAF's logs.", + "guid": "b123071a-5416-4415-a33e-a3ad2c2de732", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/app-service/networking/app-gateway-with-service-endpoints", "services": [ - "FrontDoor", - "WAF" + "Monitor", + "AppGW", + "AppSvc", + "WAF", + "FrontDoor" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Front Door with WAF to securely publish ARO applications to the internet, especially in multi-region environments.", + "severity": "High", + "subcategory": "Network Security", + "text": "Use a WAF in front of App Service", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "9e8a03f9-7879-4424-b626-786d60b96c97", - "id": "B03.02", - "link": "https://learn.microsoft.com/azure/openshift/howto-secure-openshift-with-front-door", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Make sure the WAF cannot be bypassed by locking down access to only the WAF. Use a combination of Access Restrictions, Service Endpoints and Private Endpoints.", + "guid": "165c3acb-ef4a-4be1-b8d3-9fda47768314", + "id": "A04.05", + "link": "https://learn.microsoft.com/azure/app-service/networking-features#access-restrictions", "services": [ - "PrivateLink", - "FrontDoor" + "WAF", + "PrivateLink" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "If exposing an app on ARO with Azure Front Door, use private link to connect Front Door with the ARO router.", + "severity": "High", + "subcategory": "Network Security", + "text": "Avoid for WAF to be bypassed", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "be985190-4838-435c-a86b-b2912155a114", - "id": "B03.03", - "link": "https://learn.microsoft.com/azure/openshift/howto-restrict-egress", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Set minimum TLS policy to 1.2 in App Service configuration.", + "graph": "appserviceresources | where type =~ 'microsoft.web/sites/config' | extend compliant = (properties.MinTlsVersion>=1.2) | distinct id,compliant", + "guid": "c115775c-2ea5-45b4-9ad4-8408ee72734b", + "id": "A04.06", + "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-tls-versions", "services": [ - "Firewall", - "NVA", + "AppSvc", "AzurePolicy" ], "severity": "Medium", - "subcategory": "Internet", - "text": "If your security policy requires you to inspect all outbound internet traffic that's generated in the ARO cluster, secure egress network traffic by using Azure Firewall or an NVA.", + "subcategory": "Network Security", + "text": "Set minimum TLS policy to 1.2", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "75e39f54-0acc-4cd9-9937-6bcda3750ab2", - "id": "B04.01", - "link": "https://learn.microsoft.com/azure/openshift/howto-create-private-cluster-4x", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Configure App Service to use HTTPS only. This causes App Service to redirect from HTTP to HTTPS. Strongly consider the use of HTTP Strict Transport Security (HSTS) in your code or from your WAF, which informs browsers that the site should only be accessed using HTTPS.", + "graph": "where (type=='microsoft.web/sites' and (kind == 'app' or kind == 'app,linux' )) | extend compliant = (properties.httpsOnly==true) | distinct id,compliant", + "guid": "475ba18f-dbf5-490c-b65d-e8e03f9bcbd4", + "id": "A04.07", + "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-https", "services": [ - "AzurePolicy" + "WAF", + "AppSvc" ], "severity": "High", - "subcategory": "Private access", - "text": "If your security policy requires you to use a private IP address for the OpenShift API, deploy a private ARO cluster.", + "subcategory": "Network Security", + "text": "Use HTTPS only", "waf": "Security" }, { - "category": "Network topology and connectivity", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "ab039da6-d54d-47c8-a29d-b107d5325ae6", - "id": "B04.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Do not use wildcards in your CORS configuration, as this allows all origins to access the service (thereby defeating the purpose of CORS). Specifically only allow the origins that you expect to be able to access the service.", + "guid": "68266abc-a264-4f9a-89ae-d9c55d04c2c3", + "id": "A04.08", + "link": "https://learn.microsoft.com/azure/app-service/app-service-web-tutorial-rest-api", "services": [ - "PrivateLink", - "ACR" + "Storage" ], - "severity": "Medium", - "subcategory": "Private access", - "text": "Use Azure Private Link to secure network connections to managed Azure services, including to Azure Container Registry.", + "severity": "High", + "subcategory": "Network Security", + "text": "Wildcards must not be used for CORS", "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "25ca44e4-685e-4222-9ace-8bb12307ca5f", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-enable-arc-enabled-clusters", - "services": [ - "Monitor" - ], + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Remote debugging must not be turned on in production as this opens additional ports on the service which increases the attack surface. Note that the service does turn of remote debugging automatically after 48 hours.", + "graph": "appserviceresources | where type =~ 'microsoft.web/sites/config' | extend compliant = (properties.RemoteDebuggingEnabled == false) | distinct id,compliant", + "guid": "d9bd3baf-cda3-4b54-bb2e-b03dd9a25827", + "id": "A04.09", + "link": "https://learn.microsoft.com/azure/app-service/configure-common#configure-general-settings", + "services": [], "severity": "High", - "subcategory": "Operations", - "text": "Establish a monitoring process using the inbuilt Prometheus, OpenShift Logging or Container Insights integration.", - "waf": "Operations" + "subcategory": "Network Security", + "text": "Turn off remote debugging", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "16f154e3-aa36-4928-89e7-e216183687af", - "id": "C01.02", - "link": "https://docs.openshift.com/container-platform/4.13/cicd/pipelines/understanding-openshift-pipelines.html", - "services": [], + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Enable Defender for App Service. This (amongst other threats) detects communications to known malicious IP addresses. Review the recommendations from Defender for App Service as part of your operations.", + "guid": "18d2ddb1-0725-4769-be66-91a4834ac932", + "id": "A04.10", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-app-service-introduction", + "services": [ + "Defender", + "AppSvc" + ], "severity": "Medium", - "subcategory": "Operations", - "text": "Automate the application delivery process through DevOps practices and CI/CD solutions, such as Pipelines/GitOps provided by OpenShift.", - "waf": "Operations" + "subcategory": "Network Security", + "text": "Enable Defender for Cloud - Defender for App Service", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "467a1f89-35bd-4a43-924f-14811533182a", - "id": "C01.03", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", - "services": [], - "severity": "Low", - "subcategory": "Operations", - "text": "Whenever possible, remove the service state from inside containers. Instead, use an Azure platform as a service (PaaS) that supports multiregion replication.", - "waf": "Operations" + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Azure provides DDoS Basic protection on its network, which can be improved with intelligent DDoS Standard capabilities which learns about normal traffic patterns and can detect unusual behavior. DDoS Standard applies to a Virtual Network so it must be configured for the network resource in front of the app, such as Application Gateway or an NVA.", + "guid": "223ece80-b123-4071-a541-6415833ea3ad", + "id": "A04.11", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "services": [ + "VNet", + "AppGW", + "WAF", + "NVA", + "EventHubs", + "DDoS" + ], + "severity": "Medium", + "subcategory": "Network Security", + "text": "Enable DDOS Protection Standard on the WAF VNet", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "1b7da8cf-aa66-4e15-b4d5-ada97dc3e232", - "id": "C01.04", - "link": "https://learn.microsoft.com/azure/openshift/howto-create-a-storageclass", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Where using images stored in Azure Container Registry, pull these over a virtual network from Azure Container Registry using its private endpoint and the app setting 'WEBSITE_PULL_IMAGE_OVER_VNET'.", + "guid": "2c2de732-165c-43ac-aef4-abe1f8d39fda", + "id": "A04.12", + "link": "https://learn.microsoft.com/azure/app-service/configure-custom-container#use-an-image-from-a-network-protected-registry", "services": [ - "Storage" + "VNet", + "ACR", + "PrivateLink" ], - "severity": "Low", - "subcategory": "Operations", - "text": "Use RWX storage with inbuilt Azure Files storage class.", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Network Security", + "text": "Pull containers over a Virtual Network", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "6bb235c7-05e1-4696-bded-fa8a4c8cdec4", - "id": "C02.01", - "link": "https://docs.openshift.com/container-platform/4.13/nodes/clusters/nodes-cluster-limit-ranges.html", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Conduct a penetration test on the web application following the penetration testing rules of engagement.", + "guid": "eb2eb03d-d9a2-4582-918d-2ddb10725769", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/security/fundamentals/pen-testing", "services": [], "severity": "Medium", - "subcategory": "Performance", - "text": "Use pod requests and limits to manage the compute resources within a cluster.", - "waf": "Performance" + "subcategory": "Penetration Testing", + "text": "Conduct a penetration test", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "c620c30c-14ee-4b7f-9ae8-d9b3fec228e7", - "id": "C02.02", - "link": "https://docs.openshift.com/container-platform/4.13/applications/quotas/quotas-setting-per-project.html", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", + "guid": "19aed9c5-5d04-4c2c-9919-ca0b2c12159e", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/devsecops-in-azure", "services": [], "severity": "Medium", - "subcategory": "Performance", - "text": "Enforce resource quotas on projects.", - "waf": "Performance" + "subcategory": "Vulnerability Management", + "text": "Deploy validated code", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "87ab177a-db59-4f6b-a613-334fd09dc234", - "id": "C02.03", - "link": "https://docs.openshift.com/container-platform/4.13/machine_management/applying-autoscaling.html", + "category": "Security", + "checklist": "Azure App Security Review", + "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", + "guid": "114b933d-f574-4ecc-ad9b-d3bafcda3b54", + "id": "A06.02", + "link": "https://learn.microsoft.com/azure/app-service/overview-patch-os-runtime", "services": [], "severity": "High", - "subcategory": "Performance", - "text": "Define ClusterAutoScaler and MachineAutoScaler to scale machines when your cluster runs out of resources to support more deployments.", - "waf": "Performance" + "subcategory": "Vulnerability Management", + "text": "Use up-to-date platforms, languages, protocols and frameworks", + "waf": "Security" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "19db6128-1269-4040-a4ba-4d3e0804276d", - "id": "C03.01", - "link": "https://learn.microsoft.com/azure/openshift/support-policies-v4#supported-virtual-machine-sizes", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "a95b86ad-8840-48e3-9273-4b875ba18f20", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", "services": [ - "VM" + "Monitor", + "Cost" ], - "severity": "High", - "subcategory": "Reliability", - "text": "Use virtual machine sizes that are large enough to contain multiple container instances so you get the benefits of increased density, but not so large that your cluster can't handle the workload of a failing node.", - "waf": "Reliability" - }, - { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "4b98b15c-8b31-4aa5-aceb-58889135e227", - "id": "C03.02", - "link": "https://docs.openshift.com/container-platform/4.13/machine_management/deploying-machine-health-checks.html", - "services": [], - "severity": "High", - "subcategory": "Reliability", - "text": "Deploy machine health checks to automatically repair damaged machines in a machine pool.", - "waf": "Reliability" + "subcategory": "Azure Monitor - enforce data collection rules", + "text": "Data collection rules in Azure Monitor -https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-rule-overview", + "training": "https://azure.microsoft.com/pricing/reservations/" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "896d31b6-6c67-4ba5-a119-c08e8f5d587c", - "id": "C03.03", - "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-metric-alerts", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "45901365-d38e-443f-abcb-d868266abca2", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", "services": [ - "Monitor" + "Cost", + "Backup" ], - "severity": "High", - "subcategory": "Reliability", - "text": "Use an alerting system to provide notifications when things need direct action: Container Insights metric alerts or in-built Alerting UI.", - "waf": "Reliability" + "subcategory": "Backup", + "text": "check backup instances with the underlying datasource not found" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "7e9ced16-acd1-476e-b9b2-41a998a57ae7", - "id": "C03.04", - "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview#availability-zones", - "services": [], - "severity": "High", - "subcategory": "Reliability", - "text": "Ensure that the cluster is created in a region that supports AZs and create a machine set for each AZ.", - "waf": "Reliability" + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "64f9a19a-f29c-495d-94c6-c7919ca0f6c5", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "services": [ + "Cost" + ], + "subcategory": "delete/archive", + "text": "delete or archive unassociated services (disks, nics, ip addresses etc)" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "7b997e71-1b7d-4a8c-baa6-6e15d4d5ada9", - "id": "C03.05", - "link": "https://docs.openshift.com/container-platform/4.13/machine_management/creating-infrastructure-machinesets.html", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "659d3958-fd77-4289-a835-556df2bfe456", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "AKS" + "Cost" ], - "severity": "Low", - "subcategory": "Reliability", - "text": "Create infrastructure machine sets to hold infrastructure components. Apply specific Kubernetes labels to these machines and then update the infrastructure components to run on only those machines.", - "waf": "Reliability" + "subcategory": "delete/archive", + "text": "consider snooze and stop technique (snooze a service after x days, stop after 2x, delete/deallocate after 3x)" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "7dc3e232-6bb2-435c-905e-1696fdedfa8a", - "id": "C03.06", - "link": "https://learn.microsoft.com/azure/openshift/howto-create-a-backup#create-a-backup-with-velero-to-include-snapshots", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "3b0d834a-3487-426d-b69c-6b5c2a26494b", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ + "Storage", + "Cost", "Backup" ], - "severity": "Medium", - "subcategory": "Reliability", - "text": "Create application backup and plan for restore and include persistent volumes in the backup.", - "waf": "Reliability" - }, - { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "81c12318-1a64-4174-8583-3fb4ae3c2df7", - "id": "C03.07", - "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-priority.html", - "services": [], - "severity": "Low", - "subcategory": "Reliability", - "text": "Use pod priorities, so that in case of limited resources the most critical pods will run.", - "waf": "Reliability" + "subcategory": "delete/archive", + "text": "delete or archive unused resources (old backups, logs, storage accounts, etc...)" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "43166c3b-cbe0-45bb-b209-d4a0da577784", - "id": "C04.01", - "link": "https://docs.openshift.com/container-platform/4.13/architecture/admission-plug-ins.html", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "69bad37a-ad53-4cc7-ae1d-76667357c449", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "AzurePolicy" + "Storage", + "Cost", + "Backup", + "ASR" ], - "severity": "Low", - "subcategory": "Security", - "text": "Regulate cluster functions using admission plug-ins, which are commonly used to enforce security policy, resource limitations, or configuration requirements.", - "waf": "Security" + "subcategory": "delete/archive", + "text": "consider a good balance between site recovery storage and backup for non mission critical applications" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "24d21678-5d2f-4a56-a56a-d48408fe8273", - "id": "C04.02", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-geo-replication", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "674b5ed8-5a85-49c7-933b-e2a1a27b765a", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "services": [ - "ACR" + "Monitor", + "Cost" ], - "severity": "Low", - "subcategory": "Security", - "text": "Store your container images in Azure Container Registry and geo-replicate the registry to each region.", - "waf": "Security" + "subcategory": "Log Analytics retention for workspaces", + "text": "check spending and savings opportunities among the 40 different log analytics workspaces- use different retention and data collection for nonprod workspaces-create daily cap for awareness and tier sizing - If you do set a daily cap, in addition to creating an alert when the cap is reached,ensure that you also create an alert rule to be notified when some percentage has been reached (90% for example). - consider workspace transformation if possible - https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-transformations#workspace-transformation-dcr ", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/understand-work-scopes" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "4c486ba2-80dc-4059-8cf7-5ee8e1309ccc", - "id": "C05.01", - "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-vertical-autoscaler.html", - "services": [], - "severity": "Medium", - "subcategory": "Workload", - "text": "Optimize the CPU and memory request values, and maximize the efficiency of the cluster resources using vertical pod autoscaler.", - "waf": "Performance" + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "91be1f38-8ef3-494c-8bd4-63cbbac75819", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "services": [ + "Storage", + "Cost", + "AzurePolicy" + ], + "subcategory": "Policy", + "text": "enforce a purging log policy and automation (if needed, logs can be moved to cold storage)", + "training": "https://www.youtube.com/watch?v=nHQYcYGKuyw" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "d579366b-cda2-4750-aa1a-bfe9d55d14c3", - "id": "C05.02", - "link": "https://docs.openshift.com/container-platform/4.13/applications/application-health.html", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "59bb91a3-ed90-4cae-8cc8-4c37b6b780cb", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "Monitor" + "Cost" ], - "severity": "Medium", - "subcategory": "Workload", - "text": "Add health probes to your pods to monitor application health. Make sure pods contain livenessProbe and readinessProbe. Use Startup probes to determine the point at which the application has started up.", - "waf": "Reliability" + "subcategory": "run orphaned resources workbook - delete or snooze ghost items", + "text": "https://github.com/dolevshor/azure-orphan-resources", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "c4929cb1-b3d1-4325-ae12-4ba34d0685ed", - "id": "C05.03", - "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-autoscaling.html", - "services": [], - "severity": "Medium", - "subcategory": "Workload", - "text": "Scale pods to meet demand using horizontal pod autoscaler.", - "waf": "Reliability" + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "9fe5c464-89d4-457a-a27c-3874d0102cac", + "id": "A07.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "services": [ + "Cost" + ], + "subcategory": "shutdown/deallocate", + "text": "shutdown underutilized instances", + "training": "https://learn.microsoft.com/azure/cost-management-billing/understand/analyze-unexpected-charges" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "dce9be3b-b0dd-4b3b-95fb-2ec14eeaa359", - "id": "C05.04", - "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-configuring.html#nodes-pods-pod-distruption-about_nodes-pods-configuring", + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "6aae01e6-a84d-4e5d-b36d-1d92881a1bd5", + "id": "A08.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "Cost" + "VM", + "Storage", + "Cost", + "Backup" ], - "severity": "Medium", - "subcategory": "Workload", - "text": "Use disruption budgets to ensure the required number of pod replicas exist to handle expected application load.", - "waf": "Reliability" + "subcategory": "stopped/deallocated VMs: check disks", + "text": "check that the disks are really needed, if not: delete. If they are needed, find lower storage tiers or use backup -", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/manage-automation" }, { - "category": "Operations management", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "2829e2ed-b217-4367-9aff-6791b4935ada", - "id": "C05.05", - "link": "https://docs.openshift.com/container-platform/4.13/nodes/scheduling/nodes-scheduler-pod-topology-spread-constraints.html", - "services": [], - "severity": "Medium", - "subcategory": "Workload", - "text": "Use pod topology constraints to automatically schedule pods on nodes throughout the cluster.", - "waf": "Reliability" - }, - { - "category": "Platform Automation", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "42324ece-81c1-4231-a1a6-417415833fb4", - "id": "D01.01", - "link": "https://docs.openshift.com/container-platform/4.13/applications/deployments/route-based-deployment-strategies.html", - "services": [], - "severity": "Low", - "subcategory": "Workload", - "text": "Consider blue/green or canary strategies to deploy new releases of application.", - "waf": "Operations" - }, - { - "category": "Platform Automation", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "ae3c2df7-4316-46c3-acbe-05bbe209d4a0", - "id": "D01.02", - "link": "https://docs.openshift.com/container-platform/4.13/cicd/gitops/understanding-openshift-gitops.html", - "services": [], - "severity": "Low", - "subcategory": "Workload", - "text": "Consider using Red Hat OpenShift GitOps. Red Hat OpenShift GitOps uses Argo CD to maintain cluster resources and support application CI/CD.", - "waf": "Operations" + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "d1e44a19-659d-4395-afd7-7289b835556d", + "id": "A09.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "services": [ + "Storage", + "Cost", + "AzurePolicy" + ], + "subcategory": "storage accounts lifecycle policy", + "text": "consider moving unused storage to lower tier, with customized rule - https://learn.microsoft.com/azure/storage/blobs/lifecycle-management-policy-configure ", + "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "da577784-24d2-4167-a5d2-fa56c56ad484", - "id": "E01.01", - "link": "https://learn.microsoft.com/azure/openshift/support-lifecycle", - "services": [], - "severity": "High", - "subcategory": "Control plane", - "text": "Keep your clusters on the latest OpenShift version to avoid potential security or upgrade issues.", - "waf": "Security" + "category": "Cleanup", + "checklist": "Cost Optimization Checklist", + "guid": "f2bfe456-3b0d-4834-a348-726de69c6b5c", + "id": "A10.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "services": [ + "Cost" + ], + "subcategory": "Tagging", + "text": "use specific tags for temporary items with 'delete by DATE' format - and automate monthly cleanup" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "08fe8273-4c48-46ba-880d-c0591cf75ee8", - "id": "E01.02", - "link": "https://learn.microsoft.com/azure/azure-arc/kubernetes/quickstart-connect-cluster", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "2a26494b-69ba-4d37-aad5-3cc78e1d7666", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "services": [ - "AKS", - "Arc" + "Cost" ], - "severity": "High", - "subcategory": "Control plane", - "text": "Connect Azure Red Hat OpenShift clusters to Azure Arc-enabled Kubernetes.", - "waf": "Security" + "subcategory": "db optimization", + "text": "plan for db optimization with the intent of downsizing the related services (and improve performance)" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "e1309ccc-d579-4366-acda-2750aa1abfe9", - "id": "E02.01", - "link": "https://docs.openshift.com/container-platform/4.10/security/encrypting-etcd.html", - "services": [], - "severity": "Low", - "subcategory": "Encryption", - "text": "For Azure Red Hat OpenShift 4 clusters, etcd data isn't encrypted by default, but it's recommended to enable etcd encryption to provide another layer of data security.", - "waf": "Security" + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "7357c449-674b-45ed-a5a8-59c7733be2a1", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "services": [ + "Cost" + ], + "subcategory": "app modernization", + "text": "modernizing the app towards a microservices architecture will have the effect of letting the app scale according to the single service and not the entire stack" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "d55d14c3-c492-49cb-8b3d-1325ae124ba3", - "id": "E03.01", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "a27b765a-91be-41f3-a8ef-394c2bd463cb", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "AKS", - "Arc", - "Defender" + "VM", + "Storage", + "Cost" ], - "severity": "Medium", - "subcategory": "Posture", - "text": "Use Microsoft Defender for Containers supported via Arc-enabled Kubernetes to secure clusters, containers, and applications.", - "waf": "Security" + "subcategory": "db optimization", + "text": "optimizing the DB queries will increase performance and allow better right-sizing of storage and VMs" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "4d0685ed-dce9-4be3-ab0d-db3b55fb2ec1", - "id": "E04.01", - "link": "https://learn.microsoft.com/azure/azure-arc/kubernetes/tutorial-akv-secrets-provider", + "category": "DB/APP tuning", + "checklist": "Cost Optimization Checklist", + "guid": "bac75819-59bb-491a-9ed9-0cae2cc84c37", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AKS", - "Arc", - "AKV" + "Cost" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "For applications that require access to sensitive information, use a service principal and the AKV Secrets Provider with the extension for Arc-enabled Kubernetes clusters.", - "waf": "Security" + "subcategory": "demand shaping", + "text": "using demand shaping on PaaS services will optimize costs and performances" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "4eeaa359-2829-4e2e-bb21-73676aff6791", - "id": "E05.01", - "link": "https://learn.microsoft.com/azure/aks/developer-best-practices-pod-security#secure-pod-access-to-resources", - "services": [], - "severity": "Medium", - "subcategory": "Workload", - "text": "Secure pod access to resources. Provide the least number of permissions, and avoid using root or privileged escalation.", - "waf": "Security" + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "b6b780cb-9fe5-4c46-989d-457a927c3874", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", + "services": [ + "Cost", + "Entra" + ], + "subcategory": "Advisor", + "text": "Start from the Azure Advisor page suggestions." }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "b4935ada-4232-44ec-b81c-123181a64174", - "id": "E05.02", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes#install-azure-policy-extension-for-azure-arc-enabled-kubernetes", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "d0102cac-6aae-401e-9a84-de5de36d1d92", + "id": "C01.02", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AzurePolicy", - "Monitor" + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Workload", - "text": "Monitor and enforce configuration by using the Azure Policy Extension.", - "waf": "Security" + "subcategory": "Advisor", + "text": "make sure advisor is configured for VM right sizing " }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "15833fb4-ae3c-42df-9431-66c3bcbe05bb", - "id": "E05.03", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "881a1bd5-d1e4-44a1-a659-d3958fd77289", + "id": "C02.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Defender" + "Cost" ], - "severity": "High", - "subcategory": "Workload", - "text": "Scan your images for vulnerabilities with Microsoft Defender or any other image scanning solution.", - "waf": "Security" + "subcategory": "Automation", + "text": "consider implementing IAC scripts or devops pipelines to match the cost governance process" }, { - "category": "Security", - "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", - "guid": "e209d4a0-da57-4778-924d-216785d2fa56", - "id": "E05.04", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "b835556d-f2bf-4e45-93b0-d834a348726d", + "id": "C02.02", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "Subscriptions", - "ACR" + "Monitor", + "Cost" ], - "severity": "Low", - "subcategory": "Workload", - "text": "Deploy a dedicated and private instance of Azure Container Registry to each landing zone subscription.", - "waf": "Security" + "subcategory": "Automation", + "text": "set up cost alerts for applications that have variable costs (ideally for all of them)" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Automatic instance repairs ensure that unhealthy instances are promptly identified and replaced, maintaining a set of healthy instances within your scale set.", - "guid": "7e13c105-675c-41e9-95b4-59837ff7ae7c", - "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "e69c6b5c-2a26-4494-a69b-ad37aad53cc7", + "id": "C02.03", + "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "services": [ - "VM" + "Cost" ], - "severity": "Low", - "subcategory": "VM Scale Sets", - "text": "Enable automatic instance repairs for enhanced VM Scale Sets resiliency", - "waf": "Reliability" + "subcategory": "Automation", + "text": "Use Azure Automation: Automate repetitive tasks can help you save time and resources, reducing costs in the process. " }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Ensure that Azure Backup is utilized appropriately to meet your organization's resiliency requirements for Azure virtual machines (VMs).", - "guid": "4d874a74-8b66-42d6-b150-512a66498f6d", - "link": "https://learn.microsoft.com/azure/backup/backup-azure-vms-introduction", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "8e1d7666-7357-4c44-a674-b5ed85a859c7", + "id": "C02.04", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "VM", - "Backup" + "Cost" ], - "severity": "High", - "subcategory": "Virtual Machines", - "text": "Consider Azure Backup to meet your resiliency requirements for Azure VMs", - "waf": "Reliability" + "subcategory": "Automation", + "text": "run orphaned resources workbook" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Single Instance VMs using Premium SSD or Ultra Disk for all Operating System Disks and Data Disks are guaranteed to have Virtual Machine Connectivity of at least 99.9%", - "guid": "8052d88e-79d1-47b7-9b22-a5a67e7a8ed4", - "link": "https://learn.microsoft.com/azure/virtual-machines/disks-types", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "733be2a1-a27b-4765-a91b-e1f388ef394c", + "id": "C03.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "services": [ - "VM" + "Storage", + "Cost" ], - "severity": "High", - "subcategory": "Virtual Machines", - "text": "Use Premium or Ultra disks for production VMs", - "waf": "Reliability" + "subcategory": "Baseline", + "text": "try and establish a baseline of monthly spending and an acceptable saving target against the baseline (new services will not be optimized at this stage)" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Azure automatically replicates managed disks within a region to ensure data durability and protect against single-point failures.", - "guid": "b31e38c3-f298-412b-8363-cffe179b599d", - "link": "https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "2bd463cb-bac7-4581-a59b-b91a3ed90cae", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "VM" + "Cost", + "AzurePolicy" ], - "severity": "High", - "subcategory": "Virtual Machines", - "text": "Ensure Managed Disks are used for all VMs", - "waf": "Reliability" + "subcategory": "Baseline", + "text": "establish a cost optimization baseline by using a policy that tags every new resource as #NEW" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Temporary disks are intended for short-term storage of non-persistent data such as page files, swap files, or SQL Server tempdb. Storing persistent data on temporary disks can lead to data loss during maintenance events or VM redeployment.", - "guid": "e0d5973c-d4ce-432c-8881-37f6f7c4c0d4", - "link": "https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview#temporary-disk", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "2cc84c37-b6b7-480c-a9fe-5c46489d457a", + "id": "C03.03", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "services": [ - "VM", - "Storage", - "SQL" + "Cost" ], - "severity": "Medium", - "subcategory": "Virtual Machines", - "text": "Do not use the Temp disk for anything that is not acceptable to be lost", - "waf": "Reliability" + "subcategory": "Baseline", + "text": "Organize resources to maximize cost insights and accountability" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Co-locate your compute, storage, networking, and data resources across an availability zone, and replicate this arrangement in other availability zones.", - "guid": "e514548d-2447-4ec6-9138-b8200f1ce16e", - "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "927c3874-d010-42ca-a6aa-e01e6a84de5d", + "id": "C04.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", "services": [ - "VM", - "ACR", - "Storage" + "Cost" ], - "severity": "Medium", - "subcategory": "Virtual Machines", - "text": "Leverage Availability Zones for your VMs in regions where they are supported", - "waf": "Reliability" + "subcategory": "Budgets", + "text": "Create budgets" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Use at least two VMs in Availability Sets to isolate VMs on different fault and update domains.", - "guid": "5a785d6f-e96c-496a-b884-4cf3b2b38c88", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability-set-overview", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "e36d1d92-881a-41bd-9d1e-44a19659d395", + "id": "C05.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", "services": [ - "VM" + "Cost" ], - "severity": "Medium", - "subcategory": "Virtual Machines", - "text": "For regions that do not support Availability Zones deploy VMs into Availability Sets", - "waf": "Reliability" + "subcategory": "Cost Analysis", + "text": "in cost analysis - use daily granularity, grouped by service name to analyze the spending of the past 3 months and identify the top 3 spenders" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Azure provides multiple options for VM redundancy to meet different requirements (Availability Zones, Virtual Machine Scale Sets, Availability Sets, Azure Site Recovery)", - "guid": "6ba2c021-4991-414a-9d3c-e574dccbd979", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "8fd77289-b835-4556-bf2b-fe4563b0d834", + "id": "C05.02", + "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "services": [ - "VM", - "ASR" + "Cost" ], - "severity": "High", - "subcategory": "Virtual Machines", - "text": "Avoid running a production workload on a single VM", - "waf": "Reliability" + "subcategory": "Cost Analysis", + "text": "check daily for cost spikes and anomalies (ideally with automatic billing exports)" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Azure Site Recovery enables you to achieve low RTO (Recovery Time Objective) for your Azure and hybrid VMs by providing continuous replication and failover capabilities.", - "guid": "2a6bcca2-b5fe-4a1e-af3d-d95d48c7c891", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "a348726d-e69c-46b5-a2a2-6494b69bad37", + "id": "C05.03", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "services": [ - "VM", - "AVS", - "ASR" + "Cost" ], - "severity": "High", - "subcategory": "Virtual Machines", - "text": "For Azure and on-premises VMs (Hyper-V/Phyiscal/VMware) with low RTO requirements use Azure Site Recovery", - "waf": "Reliability" + "subcategory": "Cost Analysis", + "text": "automate cost retrieval for deep analysis or integration" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "By using Capacity Reservations, you can effectively manage capacity for critical workloads, ensuring resource availability in specified regions.", - "guid": "bd7bb012-f7b9-45e0-9e15-8e3ea3992c2d", - "link": "https://learn.microsoft.com/azure/virtual-machines/capacity-reservation-overview", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "aad53cc7-8e1d-4766-9735-7c449674b5ed", + "id": "C06.01", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "services": [ - "VM" + "Cost", + "ACR" ], - "severity": "Low", - "subcategory": "Virtual Machines", - "text": "Use Capacity Reservations for critical workloads that require guaranteed capacity", - "waf": "Reliability" + "subcategory": "free services", + "text": "Take advantage of Azure free services: Azure offers a number of free services, such as DevOps, Azure Container Registry, and Azure Logic Apps, that can help you save costs on development and operations. " }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "By ensuring that the necessary quotas are increased in your DR region before testing failover with ASR, you can avoid any potential resource constraints during the recovery process for failed over VMs.", - "guid": "e6e2065b-3a76-4af4-a691-e8939ada4666", - "link": "https://learn.microsoft.com/azure/quotas/per-vm-quota-requests", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "96c96ad8-844c-4f3b-8b38-c886ba2c0214", + "id": "C07.01", + "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "services": [ - "VM", - "ASR" + "Cost" ], - "severity": "Medium", - "subcategory": "Virtual Machines", - "text": "Increase quotas in DR region before testing failover with ASR", - "waf": "Reliability" + "subcategory": "Tagging", + "text": "Tag shared resources" }, { - "category": "Compute", - "checklist": "Resiliency Review", - "description": "Scheduled Events is an Azure Metadata Service that provides information about upcoming maintenance events for virtual machines (VMs). By leveraging Scheduled Events, you can proactively prepare your applications for VM maintenance, minimizing disruption and improving the availability of your VMs.", - "guid": "6d3b475a-5c7a-4cbe-99bb-e64dd8902e87", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/scheduled-events", + "category": "Process Administration", + "checklist": "Cost Optimization Checklist", + "guid": "99014a5d-3ce5-474d-acbd-9792a6bcca2b", + "id": "C07.02", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "services": [ - "VM" + "Cost" ], - "severity": "Low", - "subcategory": "Virtual Machines", - "text": "Utilize Scheduled Events to prepare for VM maintenance", - "waf": "Reliability" + "subcategory": "Tagging", + "text": "consider using tags to all services for cost allocation" }, { - "category": "Data", - "checklist": "Resiliency Review", - "description": "Use Zone-redundant Storage (ZRS) in the primary region for scenarios that require high availability and for restricting replication to a particular country or region. For protection against regional disasters, use Geo-zone-redundant Storage (GZRS), which combines ZRS in the primary region with geo-replication to a secondary region?.", - "guid": "48c7c891-dcb1-4f7d-9769-ae568ba38d4a", - "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "4fea1dbf-3dd9-45d4-ac7c-891dcb1f7d57", + "id": "D01.01", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "services": [ - "Storage" + "Cost" ], - "severity": "Medium", - "subcategory": "Storage Accounts", - "text": "Choose the most appropriate data redundancy option for Azure Storage based on your requirements", - "waf": "Reliability" + "subcategory": "automation", + "text": "consider Reservation automation to track and promptly react to changes" }, { - "category": "Data", - "checklist": "Resiliency Review", - "description": "Assigning a Delete lock to your storage account helps protect the availability of your data, minimizing the risk of disruptions to your business operations.", - "guid": "85e2213d-bd7b-4b01-8f7b-95e06e158e3e", - "link": "https://learn.microsoft.com/azure/storage/common/lock-account-resource", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "description": "check by searching the Meter Category Licenses in the Cost analysys", + "guid": "59ae568b-a38d-4498-9e22-13dbd7bb012f", + "id": "D02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "services": [ - "Storage" + "SQL", + "VM", + "Cost", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Storage Accounts", - "text": "Apply a Delete lock to prevent accidental or malicious deletion of storage accounts", - "waf": "Reliability" + "subcategory": "check AHUB is applied to all Windows VMs, RHEL and SQL", + "text": "run the script on all windows VMs https://learn.microsoft.com/azure/virtual-machines/windows/hybrid-use-benefit-licensing?ref=andrewmatveychuk.com#convert-an-existing-vm-using-azure-hybrid-benefit-for-windows-server- consider implementing a policy if windows VMs are created frequently" }, { - "category": "Data", - "checklist": "Resiliency Review", - "description": "Container soft delete protects your data from being accidentally deleted by maintaining the deleted data in the system for a specified period of time.", - "guid": "a3992c2d-e6e2-4065-a3a7-6af4a691e893", - "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-enable", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "7b95e06e-158e-42ea-9992-c2de6e2065b3", + "id": "D03.01", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "Storage" + "LoadBalancer", + "Cost" ], - "severity": "Low", - "subcategory": "Storage Accounts", - "text": "Enable soft delete for Storage Account Containers", - "waf": "Reliability" + "subcategory": "check Red Hat Licences if applicable", + "text": " this can be also put under AHUB if you already have licenses https://learn.microsoft.com/azure/virtual-machines/linux/azure-hybrid-benefit-linux?tabs=rhelpayg%2Crhelbyos%2CrhelEnablebyos%2Crhelcompliance" }, { - "category": "Data", - "checklist": "Resiliency Review", - "description": "Blob soft delete protects an individual blob and its versions, snapshots, and metadata from accidental deletes or overwrites by maintaining the deleted data in the system for a specified period of time.", - "guid": "9ada4666-7e13-4c10-96b9-153d89f89dc7", - "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-enable", - "services": [ - "Storage" + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "a76af4a6-91e8-4839-ada4-6667e13c1056", + "id": "D04.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts", + "services": [ + "Cost", + "AppSvc" ], - "severity": "Low", - "subcategory": "Storage Accounts", - "text": "Enable soft delete for blobs", - "waf": "Reliability" + "subcategory": "Functions", + "text": "saving plans will provide 17% on select app service plans" }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "Azure Backup enhanced soft delete provides critical protection against ransomware attacks by retaining deleted backups, enabling recovery from potential ransomware encryption or deletion.", - "guid": "b44be3b1-a27f-48b9-b91b-e1038df03a82", - "link": "https://learn.microsoft.com/azure/backup/backup-azure-enhanced-soft-delete-about", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "75c1e945-b459-4837-bf7a-e7c6d3b475a5", + "id": "D05.01", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "services": [ - "Backup" + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Backup", - "text": "Enable Azure Backup enhanced soft delete for improved data protection and recovery", - "waf": "Reliability" + "subcategory": "planning", + "text": "consolidate reserved VM families with flexibility option (no more than 4-5 families)", + "training": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management" }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "Azure Backup's multi-user authorization enables fine-grained control over user access to backup resources, allowing you to restrict privileges and ensure proper authentication and authorization for backup operations.", - "guid": "2cd463cb-bbc8-4ac2-a9eb-c92a43da1dae", - "link": "https://learn.microsoft.com/azure/backup/multi-user-authorization-concept", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "c7acbe49-bbe6-44dd-a9f2-e87778468d55", + "id": "D06.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "services": [ - "Backup" + "ARS", + "VM", + "Cost" ], - "severity": "Low", - "subcategory": "Backup", - "text": "Implement multi-user authorization for Azure Backup to ensure secure and controlled access to backup resources", - "waf": "Reliability" + "subcategory": "reservations/savings plans", + "text": "Utilize Azure Reserved Instances: This feature allows you to reserve VMs for a period of 1 or 3 years, providing significant cost savings compared to PAYG prices." }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "Azure Immutable Storage provides an additional layer of security by ensuring that backup data stored in the vault cannot be modified or deleted for a specified retention period. This helps safeguard your backups from ransomware attacks that may attempt to compromise or manipulate your backup data.", - "guid": "2cc88147-0607-4c1c-aa0e-614658dd458e", - "link": "https://learn.microsoft.com/azure/backup/backup-azure-immutable-vault-concept?source=recommendations&tabs=recovery-services-vault", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "a785c6fe-96c9-46ad-a844-cf3b2b38c886", + "id": "D06.02", + "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "services": [ - "Backup", - "Storage" + "Cost" ], - "severity": "Low", - "subcategory": "Backup", - "text": "Implement Immutable Storage for your vaults to protect against ransomware and prevent unauthorized modifications to backups", - "waf": "Reliability" + "subcategory": "reservations/savings plans", + "text": "plan for Azure Savings Plans for all the workloads that are dynamic and need maximum flexibility" }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "Clearly define your organization's business continuity and disaster recovery requirements for your Azure environment. This includes identifying the critical applications, data, and services that need to be protected, as well as specifying the desired recovery objectives and strategies.", - "guid": "72e52e36-11dd-458c-9a4b-1521e43a58a9", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-business-continuity-disaster-recovery", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "ba2c0214-9901-44a5-b3ce-574dccbd9792", + "id": "D06.03", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "services": [ - "ASR" + "Cost" ], - "severity": "High", - "subcategory": "Design", - "text": "Define business continuity and disaster recovery requirements", - "waf": "Reliability" + "subcategory": "reservations/savings plans", + "text": "plan for Azure Reservations for all the workloads that are less dynamic and won't change much" }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "Ensure that your Azure architectures are designed with a focus on reliability. Consider implementing fault-tolerant mechanisms, redundancy, and resiliency patterns to minimize the impact of failures and maximize the availability of your applications and services.", - "guid": "c2399c4d-7b67-4d0c-9555-62f2b3e4563a", - "link": "https://learn.microsoft.com/azure/architecture/reliability/architect", - "services": [], - "severity": "High", - "subcategory": "Design", - "text": "Implement reliability best practices in Azure architectures", - "waf": "Reliability" + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "a6bcca2b-4fea-41db-b3dd-95d48c7c891d", + "id": "D07.01", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "services": [ + "Storage", + "Cost" + ], + "subcategory": "reserve storage", + "text": "only larger disks can be reserved =>1TiB -" }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "IaC configurations can play a role in your disaster recovery plan, particularly in situations where recovery time is not time-sensitive. In the event of infrastructure recreation in a second region, IaC can be used to reproduce the necessary infrastructure.", - "guid": "fe237de2-43b1-46c3-8d7a-a9b7570449aa", - "link": "https://learn.microsoft.com/azure/well-architected/devops/automation-infrastructure", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "cb1f7d57-59ae-4568-aa38-d4985e2213db", + "id": "D08.01", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "services": [ - "RBAC", - "ASR" + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "DevOps", - "text": "Implement Infrastructure as Code (IaC) for Rapid Infrastructure Recovery", - "waf": "Reliability" + "subcategory": "reserve VMs with normalized and rationalized sizes", + "text": "after the right-sizing optimization" }, { - "category": "General", - "checklist": "Resiliency Review", - "description": "Azure offers region pairs that are geographically separated and can be used for cross-region replication and disaster recovery. These region pairs provide redundancy and protection against regional or large-scale disasters.", - "guid": "dcb1f7d5-769a-4e56-aba3-8d4a85e2213d", - "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "d7bb012f-7b95-4e06-b158-e2ea3992c2de", + "id": "D09.01", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "services": [ - "ASR" + "SQL", + "Cost", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Multi-region", - "text": "Plan for cross-region recovery by leveraging region pairs", - "waf": "Reliability" + "subcategory": "SQL Database AHUB", + "text": "check if applicable and enforce policy/change https://learn.microsoft.com/azure/azure-sql/azure-hybrid-benefit?view=azuresql&tabs=azure-portalhttps://learn.microsoft.com/azure/cost-management-billing/scope-level/create-sql-license-assignments?source=recommendations" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "By deploying an Application Gateway with a minimum instance count of two, you will have at least two instances available under normal circumstances. In the event that one of the instances encounters a problem, the other instance will handle the traffic while a new instance is being created. This approach significantly reduces the risk of service disruption and ensures a seamless experience for your users.", - "guid": "93c76286-37a5-451c-9b04-e4f1854387e5", - "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant#autoscaling-and-high-availability", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "6e2065b3-a76a-4f4a-991e-8839ada46667", + "id": "D10.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", "services": [ - "AppGW" + "SQL", + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Application Gateways", - "text": "Deploy Application Gateways with a minimum instance count of 2 to avoid instance provisioning downtime", - "waf": "Reliability" + "subcategory": "SQL Database Reservations", + "text": "the VM + licence part discount (ahub+3YRI) is around 70% discount" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "The v2 SKU offers several advantages and critical new features that enhance the availability and resilience of your application infrastructure. One notable feature supported by the v2 SKU is zone redundancy, which allows an Application Gateway deployment to span multiple Availability Zones.", - "guid": "ced126cd-032a-4f5b-8fc6-998a535e3378", - "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "e13c1056-75c1-4e94-9b45-9837ff7ae7c6", + "id": "D11.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "services": [ - "Storage", - "AppGW" + "Cost" ], - "severity": "High", - "subcategory": "Application Gateways", - "text": "Deploy Azure Application Gateway v2 for zone redundancy support", - "waf": "Reliability" + "subcategory": "tracking", + "text": "Make sure you Azure Reservations and Savings plans are close to 100% utilization or make the necessary changes to reach it." }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "Azure Front Door provides automatic failover capabilities, ensuring continuity in the event of a primary region becoming unavailable. However, during the failover process, there may be a brief period (typically 20-60 seconds) when clients cannot reach the application. It is essential to review the Azure Front Door service level agreement (SLA) to determine whether relying solely on Front Door meets your business requirements for high availability. ", - "guid": "97e31c67-d68c-4f6a-92a1-194956d697dc", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/app-service-web-app/multi-region#azure-front-door", + "category": "reservations", + "checklist": "Cost Optimization Checklist", + "guid": "d3b475a5-c7ac-4be4-abbe-64dd89f2e877", + "id": "D11.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "services": [ - "FrontDoor" + "Cost", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Azure Front Door", - "text": "Consider a redundant traffic management solution in conjunction with Azure Front Door", - "waf": "Reliability" + "subcategory": "tracking", + "text": "make sure that your reservations usage is close to 100%. If not, either enforce an allowed SKU policy or exchange the reservation" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "By implementing Traffic Manager, you can configure it to continuously monitor the health of your application endpoints and automatically redirect traffic to an alternate endpoint when necessary. This automation minimizes downtime and provides a more seamless experience for your users during disaster recovery scenarios.", - "guid": "8df03a82-2cd4-463c-abbc-8ac299ebc92a", - "link": "https://learn.microsoft.com/azure/networking/disaster-recovery-dns-traffic-manager", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "78468d55-a785-4c6f-b96c-96ad8844cf3b", + "id": "E01.01", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "services": [ - "ASR", - "TrafficManager", - "DNS", - "Monitor" + "Cost", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "DNS", - "text": "Plan for automated failover using Traffic Manager for DNS Traffic", - "waf": "Reliability" + "subcategory": "Automation", + "text": "plan and enforce a ON/OFF policy for production services, where possible" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "To eliminate a single point of failure in your on-premises DNS services and ensure reliable DNS resolution during business continuity and disaster recovery scenarios, it is recommended to utilize Azure DNS Private Resolvers in multiple regions. By deploying two or more Azure DNS private resolvers across different regions, you can enable DNS failover and achieve resiliency in your DNS infrastructure.", - "guid": "43da1dae-2cc8-4814-9060-7c1cca0e6146", - "link": "https://learn.microsoft.com/azure/dns/tutorial-dns-private-resolver-failover", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "2b38c886-ba2c-4021-9990-14a5d3ce574d", + "id": "E01.02", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "services": [ - "ASR", - "ACR", - "DNS" + "Cost", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "DNS", - "text": "Implement DNS Failover using Azure DNS Private Resolvers", - "waf": "Reliability" + "subcategory": "Automation", + "text": "plan and enforce a ON-DEMAND policy with auto-shutdown for non-production services, where possible" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "Use an on-premises data gateway cluster to avoid single points of failure and to load balance traffic across gateways.", - "guid": "89f89dc7-b44b-4e3b-8a27-f8b9e91be103", - "link": "https://learn.microsoft.com/data-integration/gateway/service-gateway-high-availability-clusters", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "ccbd9792-a6bc-4ca2-a4fe-a1dbf3dd95d4", + "id": "E02.01", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "services": [ - "ACR" + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Data Gateways", - "text": "Use on-premises data gateway clusters to ensure high availability for business-critical data", - "waf": "Reliability" + "subcategory": "Autoscale", + "text": "consider using a VMSS to match demand rather than flat sizing" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "When using ExpressRoute, it's important to design for high availability by incorporating redundancy in both the partner and customer networks. This can include multiple ExpressRoute circuits, redundant connections from your network to Microsoft, and ensuring your on-premises network equipment has redundant connections.", - "guid": "c0e7c28d-c936-4657-802b-ff4564b0d934", - "link": "https://learn.microsoft.com/azure/expressroute/designing-for-high-availability-with-expressroute", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "c1b1cd52-1e54-4a29-a9de-39ac0e7c28dc", + "id": "E02.02", + "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "services": [ - "ExpressRoute" + "AKS", + "Cost" ], - "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "Ensure redundancy within both the partner network and customer network when utilizing ExpressRoute for high availability", - "waf": "Reliability" + "subcategory": "Autoscale", + "text": "use AKS autoscaler to match your clusters usage (make sure the pods requirements match the scaler)" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "The primary circuit should handle regular traffic while the backup circuit stays ready to take over if the primary circuit fails. Utilize BGP attributes to influence routing and designate your primary and backup circuits effectively.", - "guid": "a359c373-e7dd-4616-83a3-64a907ebae48", - "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "93665720-2bff-4456-9b0d-934a359c363e", + "id": "E02.03", + "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "services": [ - "Backup", - "ExpressRoute" + "Cost" ], - "severity": "Medium", - "subcategory": "ExpressRoute", - "text": "When using multiple ExpressRoute circuits ensure that routing allows for a primary and backup", - "waf": "Reliability" + "subcategory": "Autoscale", + "text": "right-size PaaS service according to average use and accomodate spikes with auto or manual scaling" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "S2S VPN connection can provide a cost-effective, resilient backup solution in the event of an ExpressRoute circuit failure. By using S2S VPN as a failover, you can maintain connectivity to your Azure resources without relying solely on ExpressRoute.", - "guid": "ead53cc7-de2e-48aa-ab35-71549ab9153d", - "link": "https://learn.microsoft.com/azure/expressroute/use-s2s-vpn-as-backup-for-expressroute-privatepeering", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "7dd61623-a364-4a90-9eba-e38ead53cc7d", + "id": "E02.04", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "Backup", - "ExpressRoute", - "VPN", "Cost" ], - "severity": "Low", - "subcategory": "ExpressRoute", - "text": "Consider deploying site-to-site VPN as a backup for your ExpressRoute private peering", - "waf": "Reliability" + "subcategory": "Autoscale", + "text": "plan for demand shaping where applicable" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "Standard Load Balancer SKU offers an SLA of 99.99% and a higher level of service availability compared to the Basic Load Balancer SKU.", - "guid": "778468d5-5a78-45d6-be96-c96ad8844cf3", - "link": "https://learn.microsoft.com/azure/load-balancer/skus", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "e2e8aaab-3571-4549-ab91-53d89f89dc7b", + "id": "E02.05", "services": [ - "LoadBalancer" + "Cost" ], - "severity": "Medium", - "subcategory": "Load Balancers", - "text": "Leverage the Standard SKU for Load Balancers that handle traffic to production applications", - "waf": "Reliability" + "subcategory": "Autoscale", + "text": "consider implementing a service re-scaling logic within the application", + "training": "https://learn.microsoft.com/azure/cost-management-billing/savings-plan/" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "By configuring the load balancer with a zone-redundant frontend, it can serve zonal resources in any zone with a single IP address. As long as at least one zone remains healthy within the region, the IP address associated with the frontend can survive one or more zone failures. It is recommended to have multiple zonal resources, such as virtual machines from different zones, in the backend pool of the load balancer. ", - "guid": "b2b38c88-6ba2-4c02-8499-114a5d3ce574", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-standard-availability-zones", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "44be3b1a-27f8-4b9e-a1be-1f38df03a822", + "id": "E03.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "services": [ - "VM", - "LoadBalancer" + "Cost", + "Backup" ], - "severity": "Low", - "subcategory": "Load Balancers", - "text": "For load balancers, consider using a zone-redundant frontend with multiple zonal resources in the backend", - "waf": "Reliability" + "subcategory": "Backup", + "text": "Move recovery points to vault-archive where applicable (Validate)", + "training": "https://azure.microsoft.com/pricing/reservations/" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "When designing health probes for your Azure Load Balancer, it is important to follow best practices to ensure reliable and accurate monitoring of your backend instances.", - "guid": "dccbd979-2a6b-4cca-8b5f-ea1ebf3dd95d", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-custom-probe-overview#design-guidance", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "cd463cbb-bc8a-4c29-aebc-91a43da1dae2", + "id": "E04.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ + "VM", "LoadBalancer", - "Monitor" + "Cost" ], - "severity": "Low", - "subcategory": "Load Balancers", - "text": "Select the right protocol, appropriate intervals and timeouts, representative paths and probe responses when defining Load Balancer Health Probes", - "waf": "Reliability" + "subcategory": "databricks", + "text": "consider using Spot VMs with fallback where possibleconsider autotermination of clusters https://learn.microsoft.com/azure/databricks/clusters/cluster-config-best-practices#automatic-termination ", + "training": "https://andrewmatveychuk.com/how-to-audit-azure-hybrid-benefit-usage-with-azure-workbooks/" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "When choosing the best option for deploying NVAs in Azure, it is crucial to consider the vendor's recommendations and validate that the specific design has been vetted and validated by the NVA vendor. The vendor should also provide the necessary NVA configuration for seamless integration in Azure.", - "guid": "8b1188b3-c6a4-46ce-a544-451e192d3442", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "cc881470-607c-41cc-a0e6-14658dd458e9", + "id": "E05.01", + "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "services": [ - "NVA" + "Cost" ], - "severity": "High", - "subcategory": "NVAs", - "text": "Deploy Network Virtual Appliances (NVAs) in a vendor supported configuration for High Availability", - "waf": "Reliability" + "subcategory": "Functions", + "text": "Functions - Reuse connections", + "training": "https://learn.microsoft.com/azure/cost-management-billing/reservations/reservation-apis?toc=%2Fazure%2Fcost-management-billing%2Ftoc.json" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "By deploying VPN Gateways in an active-active mode, you can distribute VPN traffic across multiple gateways, improving reliability and ensuring continuous connectivity in case of failures or maintenance.", - "guid": "927139b8-2110-42db-b6ea-f11e6f843e53", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-highlyavailable", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "27139b82-1102-4dbd-9eaf-11e6f843e52f", + "id": "E05.02", + "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "services": [ - "VPN", - "ACR" + "Cost" ], - "severity": "Medium", - "subcategory": "VPN Gateways", - "text": "Deploy Azure VPN Gateways in an active-active mode to ensure high availability and redundancy for your VPN connections.", - "waf": "Reliability" + "subcategory": "Functions", + "text": "functions -Cache data locally", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/" }, { - "category": "Network", - "checklist": "Resiliency Review", - "description": "Zone-redundant SKUs ensure that your VPN gateways are physically and logically separated within a region, providing resiliency and scalability. This deployment configuration safeguards your on-premises network connectivity to Azure from zone-level failures.", - "guid": "f4722d92-8c1b-41cd-921f-54b29b9de39a", - "link": "https://learn.microsoft.com/azure/vpn-gateway/about-zone-redundant-vnet-gateways", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "4722d928-c1b1-4cd5-81e5-4a29b9de39ac", + "id": "E05.03", + "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "services": [ - "VPN" + "Storage", + "Cost" ], - "severity": "Medium", - "subcategory": "VPN Gateways", - "text": "Use zone-redundant SKUs when deploying VPN Gateways to enhance resilience and protect against zone-level failures", - "waf": "Reliability" + "subcategory": "Functions", + "text": "functions - Cold starts-Use the 'Run from package' functionality. This way, the code is downloaded as a single zip file. This can, for example, result in significant improvements with Javascript functions, which have a lot of node modules.Use language specific tools to reduce the package size, for example, tree shaking Javascript applications.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Apply guidance from the Microsoft cloud security benchmark related to Storage", - "guid": "d237de14-3b16-4c21-b7aa-9b64604489a8", - "id": "A01.01", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/storage-security-baseline", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "0e7c28dc-9366-4572-82bf-f4564b0d934a", + "id": "E05.04", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "services": [ - "Storage" + "Cost" ], - "severity": "Medium", - "subcategory": " Overview", - "text": "Consider the 'Azure security baseline for storage'", - "waf": "Security" + "subcategory": "Functions", + "text": "Functions -Keep your functions warm", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Azure Storage by default has a public IP address and is Internet-reachable. Private endpoints allow to securely expose Azure Storage only to those Azure Compute resources that need access, thus eliminating exposure to the public Internet", - "guid": "f42d78e7-9d17-4a73-a22a-5a67e7a8ed4b", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/storage/common/storage-private-endpoints", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "359c363e-7dd6-4162-9a36-4a907ebae38e", + "id": "E05.05", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "PrivateLink", - "Storage" + "Cost" ], - "severity": "High", - "subcategory": "Networking", - "text": "Consider using private endpoints for Azure Storage", - "waf": "Security" + "subcategory": "Functions", + "text": "when using autoscale with different functions, there might be one driving all the autoscale for all the resources - consider moving it to a separate consumption plan (and consider higher plan for CPU)" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Newly created storage accounts are created using the ARM deployment model, so that RBAC, auditing etc. are all enabled. Ensure that there are no old storage accounts with classic deployment model in a subscription", - "guid": "30e37c3e-2971-41b2-963c-eee079b598de", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/virtual-machines/migration-classic-resource-manager-overview#migration-of-storage-accounts", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "ad53cc7d-e2e8-4aaa-a357-1549ab9153d8", + "id": "E05.06", + "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", "services": [ - "Subscriptions", - "RBAC", - "Storage" + "Cost" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "Ensure older storage accounts are not using 'classic deployment model'", - "waf": "Security" + "subcategory": "Functions", + "text": "Function apps in a given plan are all scaled together, so any issues with scaling can affect all apps in the plan." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Leverage Microsoft Defender to learn about suspicious activity and misconfigurations.", - "guid": "fc5972cd-4cd2-41b0-a803-7f5e6b4bfd3d", - "id": "A03.02", - "link": "https://learn.microsoft.com/azure/storage/common/azure-defender-storage-configure", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "9f89dc7b-44be-43b1-a27f-8b9e91be1f38", + "id": "E05.07", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "services": [ - "Storage", - "Defender" + "Cost" ], - "severity": "High", - "subcategory": "Governance", - "text": "Enable Microsoft Defender for all of your storage accounts", - "waf": "Security" + "subcategory": "Functions", + "text": "Am I billed for 'await time' ?This question is typically asked in the context of a C# function that does an async operation and waits for the result, e.g. await Task.Delay(1000) or await client.GetAsync('http://google.com'). The answer is yes - the GB second calculation is based on the start and end time of the function and the memory usage over that period. What actually happens over that time in terms of CPU activity is not factored into the calculation.One exception to this rule is if you are using durable functions. You are not billed for time spent at awaits in orchestrator functions.apply demand shaping techinques where possible (dev environments?) https://github.com/Azure-Samples/functions-csharp-premium-scaler" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "The soft-delete mechanism allows to recover accidentally deleted blobs.", - "guid": "503547c1-447e-4c66-828a-7100f1ce16dd", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-overview", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "df03a822-cd46-43cb-abc8-ac299ebc91a4", + "id": "E06.01", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "services": [ - "Storage" + "Cost" ], - "severity": "Medium", - "subcategory": "Data Availability", - "text": "Enable 'soft delete' for blobs", - "waf": "Security" + "subcategory": "Networking", + "text": "evaluate your network topology against networking costs and where applicable reduce the egress and peering data" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Consider selectively disabling 'soft delete' for certain blob containers, for example if the application must ensure that deleted information is immediately deleted, e.g. for confidentiality, privacy or compliance reasons. ", - "guid": "3f1d5e87-2e52-4e36-81cc-58b4a4b1510e", - "id": "A05.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-enable", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "3da1dae2-cc88-4147-8607-c1cca0e61465", + "id": "E06.02", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "Storage" + "EventHubs", + "FrontDoor", + "Cost" ], - "severity": "Medium", - "subcategory": "Confidentiality", - "text": "Disable 'soft delete' for blobs", - "waf": "Security" + "subcategory": "Networking", + "text": "Frontdoor - Turn off the default homepageIn the application settings of your App, set AzureWebJobsDisableHomepage to true. This will return a 204 (No Content) to the PoP so only header data is returned." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Soft delete for containers enables you to recover a container after it has been deleted, for example recover from an accidental delete operation.", - "guid": "43a58a9c-2289-4c3d-9b57-d0c655462f2a", - "id": "A06.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-overview", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "8dd458e9-2713-49b8-8110-2dbd6eaf11e6", + "id": "E06.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "services": [ - "Storage" + "FrontDoor", + "Cost", + "AppSvc" ], - "severity": "High", - "subcategory": "Data Availability", - "text": "Enable 'soft delete' for containers", - "waf": "Security" + "subcategory": "Networking", + "text": "Frontdoor -Route to something that returns nothingEither set up a Function, Function Proxy, or add a route in your WebApp that returns 200 (OK) and sends no or minimal content. The advantage of this is you will be able to log out when it is called." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Consider selectively disabling 'soft delete' for certain blob containers, for example if the application must ensure that deleted information is immediately deleted, e.g. for confidentiality, privacy or compliance reasons. ", - "guid": "3e3453a3-c863-4964-ab65-2d6c15f51296", - "id": "A07.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-enable", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "f843e52f-4722-4d92-ac1b-1cd521e54a29", + "id": "E07.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "services": [ - "Storage" + "Cost" ], - "severity": "Medium", - "subcategory": "Confidentiality", - "text": "Disable 'soft delete' for containers", - "waf": "Security" + "subcategory": "PaaS", + "text": "consider using free tiers where applicable for all non-production environments" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Prevents accidental deletion of a storage account, by forcing the user to first remove the deletion lock, prior to deletion", - "guid": "5398e6de-d227-4dd1-92b0-6c21d7999a64", - "id": "A08.01", - "link": "https://learn.microsoft.com/azure/storage/common/lock-account-resource", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "b9de39ac-0e7c-428d-a936-657202bff456", + "id": "E08.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "services": [ - "Storage" + "Cost" ], - "severity": "High", - "subcategory": "Data Availability", - "text": "Enable resource locks on storage accounts", - "waf": "Security" + "subcategory": "serverless", + "text": "using serverless patterns for spikes can help keeping costs down" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Consider 'legal hold' or 'time-based retention' policies for blobs, so that is is impossible to delete the blob, the container, or the storage account. Please note that 'impossible' actually means 'impossible'; once a storage account contains an immutable blob, the only way to 'get rid' of that storage account is by cancelling the Azure subscription.", - "guid": "6f4389a8-f42c-478e-98c0-6a73a22a4956", - "id": "A09.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/immutable-storage-overview", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "7e31c67d-68cf-46a6-8a11-94956d697dc3", + "id": "E09.01", + "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "services": [ - "Subscriptions", "Storage", - "AzurePolicy" + "Cost" ], - "severity": "High", - "subcategory": "Data Availability, Compliance", - "text": "Consider immutable blobs", - "waf": "Security" + "subcategory": "Storage", + "text": "consider archiving tiers for less used data" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Consider disabling unprotected HTTP/80 access to the storage account, so that all data transfers are encrypted, integrity protected, and the server is authenticated. ", - "guid": "e7a8dc4a-20e2-47c3-b297-11b1352beee0", - "id": "A10.01", - "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "a2ed27b2-d186-4f1a-8252-bddde68a487c", + "id": "E09.02", + "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "services": [ - "Storage" + "Storage", + "Cost" ], - "severity": "High", - "subcategory": "Networking", - "text": "Require HTTPS, i.e. disable port 80 on the storage account", - "waf": "Security" + "subcategory": "Storage", + "text": "check disk sizes where the size does not match the tier (i.e. A 513 GiB disk will pay a P30 (1TiB) and consider resizing" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "When configuring a custom domain (hostname) on a storage account, check whether you need TLS/HTTPS; if so, you might have to put Azure CDN in front of your storage account.", - "guid": "79b588de-fc49-472c-b3cd-21bf77036e5e", - "id": "A10.02", - "link": "https://learn.microsoft.com/azure/storage/blobs/storage-custom-domain-name", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "dec4861b-c3bc-410a-b77e-26e4d5a3bec2", + "id": "E09.03", + "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "services": [ - "Storage" + "Storage", + "Cost" ], - "severity": "High", - "subcategory": "Networking", - "text": "When enforcing HTTPS (disabling HTTP), check that you do not use custom domains (CNAME) for the storage account.", - "waf": "Security" + "subcategory": "Storage", + "text": "consider using standard SSD rather than Premium or Ultra where possible" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Requiring HTTPS when a client uses a SAS token to access blob data helps to minimize the risk of credential loss.", - "guid": "6b4bed3d-5035-447c-8347-dc56028a71ff", - "id": "A10.03", - "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "c4e2436b-1336-4db5-9f17-960eee0bdf5c", + "id": "E09.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "services": [ - "Storage" + "Storage", + "Cost" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Limit shared access signature (SAS) tokens to HTTPS connections only", - "waf": "Security" + "subcategory": "Storage", + "text": "For storage accounts, make sure that the chosen tier is not adding up transaction charges (it might be cheaper to move to the next tier)" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "AAD tokens should be favored over shared access signatures, wherever possible", - "guid": "e1ce15dd-3f0d-45e7-92d4-1e3611cc57b4", - "id": "A11.01", - "link": "https://learn.microsoft.com/azure/storage/common/authorize-data-access", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "c2efc5d7-61d4-41d2-900b-b47a393a040f", + "id": "E09.05", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "services": [ - "Entra", - "Storage" + "Storage", + "Cost", + "ASR" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Use Azure Active Directory (Azure AD) tokens for blob access", - "waf": "Security" + "subcategory": "Storage", + "text": "for ASR, consider using Standard SSD disks if the RPO/RTO and replication throughput allow it" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "When assigning a role to a user, group, or application, grant that security principal only those permissions that are necessary for them to perform their tasks. Limiting access to resources helps prevent both unintentional and malicious misuse of your data.", - "guid": "a4b1410d-4395-48a8-a228-9b3d6b57cfc6", - "id": "A11.02", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "d3294798-b118-48b2-a5a4-6ceb544451e1", + "id": "E10.01", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "services": [ - "RBAC", - "Entra", - "Storage" + "Storage", + "Cost" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Least privilege in IaM permissions", - "waf": "Security" + "subcategory": "storage", + "text": "storage accounts: check hot tier and/or GRS necessary" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "A user delegation SAS is secured with Azure Active Directory (Azure AD) credentials and also by the permissions specified for the SAS. A user delegation SAS is analogous to a service SAS in terms of its scope and function, but offers security benefits over the service SAS. ", - "guid": "55461e1a-3e34-453a-9c86-39648b652d6c", - "id": "A11.03", - "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json#best-practices-when-using-sas", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "92d34429-3c76-4286-97a5-51c5b04e4f18", + "id": "E10.02", + "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "services": [ - "Entra", - "Storage" + "Storage", + "Cost" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "When using SAS, prefer 'user delegation SAS' over storage-account-key based SAS.", - "waf": "Security" + "subcategory": "storage", + "text": "Disks -validate use of Premium SSD disks everywhere: for example, non-prod could swap to Standard SSD or On demand Premium SSD " }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Storage account keys ('shared keys') have very little audit capabilities. While it can be monitored on who/when fetched a copy of the keys, once the keys are in the hands of multiple people, it is impossible to attribute usage to a specific user. Solely relying on AAD authentication makes it easier to tie storage access to a user. ", - "guid": "15f51296-5398-4e6d-bd22-7dd142b06c21", - "id": "A11.04", - "link": "https://learn.microsoft.com/rest/api/storageservices/authorize-with-shared-key", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "54387e5c-ed12-46cd-832a-f5b2fc6998a5", + "id": "E11.01", + "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "services": [ + "EventHubs", "Monitor", - "Entra", - "Storage", - "AKV" + "Cost" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Consider disabling storage account keys, so that only AAD access (and user delegation SAS) is supported.", - "waf": "Security" + "subcategory": "Synapse", + "text": "Create budgets to manage costs and create alerts that automatically notify stakeholders of spending anomalies and overspending risks." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Use Activity Log data to identify 'when', 'who', 'what' and 'how' the security of your storage account is being viewed or changed (i.e. storage account keys, access policies, etc.).", - "guid": "d7999a64-6f43-489a-af42-c78e78c06a73", - "id": "A12.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/blob-storage-monitoring-scenarios#audit-account-activity", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "35e33789-7e31-4c67-b68c-f6a62a119495", + "id": "E11.02", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "services": [ - "AKV", "Storage", - "AzurePolicy", - "Monitor" + "Cost" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Consider using Azure Monitor to audit control plane operations on the storage account", - "waf": "Security" + "subcategory": "Synapse", + "text": "Export cost data to a storage account for additional data analysis." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "A key expiration policy enables you to set a reminder for the rotation of the account access keys. The reminder is displayed if the specified interval has elapsed and the keys have not yet been rotated.", - "guid": "a22a4956-e7a8-4dc4-a20e-27c3e29711b1", - "id": "A13.01", - "link": "https://learn.microsoft.com/azure/storage/common/storage-account-keys-manage?tabs=azure-portal#create-a-key-expiration-policy", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "6d697dc3-a2ed-427b-8d18-6f1a1252bddd", + "id": "E11.03", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "Entra", - "Storage", - "AzurePolicy", - "AKV" + "SQL", + "Cost" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "When using storage account keys, consider enabling a 'key expiration policy'", - "waf": "Security" + "subcategory": "Synapse", + "text": "Control costs for a dedicated SQL pool by pausing the resource when it is not in use." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "A SAS expiration policy specifies a recommended interval over which the SAS is valid. SAS expiration policies apply to a service SAS or an account SAS. When a user generates service SAS or an account SAS with a validity interval that is larger than the recommended interval, they'll see a warning.", - "guid": "352beee0-79b5-488d-bfc4-972cd3cd21bf", - "id": "A13.02", - "link": "https://learn.microsoft.com/azure/storage/common/sas-expiration-policy", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "e68a487c-dec4-4861-ac3b-c10ae77e26e4", + "id": "E11.04", + "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "services": [ - "Entra", - "Storage", - "AzurePolicy" + "Cost" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Consider configuring an SAS expiration policy", - "waf": "Security" + "subcategory": "Synapse", + "text": "Enable the serverless Apache Spark automatic pause feature and set your timeout value accordingly." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Stored access policies give you the option to revoke permissions for a service SAS without having to regenerate the storage account keys. ", - "guid": "77036e5e-6b4b-4ed3-b503-547c1347dc56", - "id": "A13.03", - "link": "https://learn.microsoft.com/rest/api/storageservices/define-stored-access-policy", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "d5a3bec2-c4e2-4436-a133-6db55f17960e", + "id": "E11.05", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "services": [ - "Entra", - "Storage", - "AzurePolicy", - "AKV" + "Cost" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Consider linking SAS to a stored access policy", - "waf": "Security" + "subcategory": "Synapse", + "text": "Create multiple Apache Spark pool definitions of various sizes." }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "guid": "028a71ff-e1ce-415d-b3f0-d5e772d41e36", - "id": "A14.01", - "link": "https://microsoft.github.io/code-with-engineering-playbook/continuous-integration/dev-sec-ops/secret-management/recipes/detect-secrets-ado/", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "ee0bdf5c-c2ef-4c5d-961d-41d2500bb47a", + "id": "E11.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "services": [ - "Storage", - "AKV" + "Cost" ], - "severity": "Medium", - "subcategory": "CI/CD", - "text": "Consider configuring your application's source code repository to detect checked-in connection strings and storage account keys.", - "waf": "Security" + "subcategory": "Synapse", + "text": "Purchase Azure Synapse commit units (SCU) for one year with a pre-purchase plan to save on your Azure Synapse Analytics costs.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Ideally, your application should be using a managed identity to authenticate to Azure Storage. If that is not possible, consider having the storage credential (connection string, storage account key, SAS, service principal credential) in Azure KeyVault or an equivalent service.", - "guid": "11cc57b4-a4b1-4410-b439-58a8c2289b3d", - "id": "A15.01", - "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-storage-keys", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "393a040f-d329-4479-ab11-88b2c5a46ceb", + "id": "E12.01", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "services": [ - "Entra", - "Storage" + "VM", + "Cost" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Consider storing connection strings in Azure KeyVault (in scenarios where managed identities are not possible)", - "waf": "Security" + "subcategory": "VM", + "text": "Use SPOT VMs for interruptible jobs: These are VMs that can be bid on and purchased at a discounted price, providing a cost-effective solution for non-critical workloads.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Use near-term expiration times on an ad hoc SAS service SAS or account SAS. In this way, even if a SAS is compromised, it's valid only for a short time. This practice is especially important if you cannot reference a stored access policy. Near-term expiration times also limit the amount of data that can be written to a blob by limiting the time available to upload to it.", - "guid": "27138b82-1102-4cac-9eae-01e6e842e52f", - "id": "A15.02", - "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "544451e1-92d3-4442-a3c7-628637a551c5", + "id": "E12.02", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "Entra", - "Storage", - "AzurePolicy" + "VM", + "Cost" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Strive for short validity periods for ad-hoc SAS", - "waf": "Security" + "subcategory": "VM", + "text": "right-sizing all VMs" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "When creating a SAS, be as specific and restrictive as possible. Prefer a SAS for a single resource and operation over a SAS which gives much broader access.", - "guid": "4721d928-c1b1-4cd5-81e5-4a29a9de399c", - "id": "A15.03", - "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "b04e4f18-5438-47e5-aed1-26cd032af5b2", + "id": "E12.03", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "services": [ - "Entra", - "Storage" + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Apply a narrow scope to a SAS", - "waf": "Security" + "subcategory": "VM", + "text": "swap VM sized with normalized and most recent sizes", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "A SAS can include parameters on which client IP addresses or address ranges are authorized to request a resource using the SAS. ", - "guid": "fd7b28dc-9355-4562-82bf-e4564b0d834a", - "id": "A15.04", - "link": "https://learn.microsoft.com/rest/api/storageservices/create-account-sas", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "fc6998a5-35e3-4378-a7e3-1c67d68cf6a6", + "id": "E12.04", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "Entra", - "Storage" + "Monitor", + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Consider scoping SAS to a specific client IP address, wherever possible", - "waf": "Security" + "subcategory": "VM", + "text": "right-sizing VMs - start with monitoring usage below 5% and then work up to 40%", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "A SAS cannot constrain how much data a client uploads; given the pricing model of amount of storage over time, it might make sense to validate whether clients uploaded maliciously large contents.", - "guid": "348b263e-6dd6-4051-8a36-498f6dbad38e", - "id": "A15.05", + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "2a119495-6d69-47dc-9a2e-d27b2d186f1a", + "id": "E12.05", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "Entra", - "Storage" + "VM", + "Cost" ], - "severity": "Low", - "subcategory": "Identity and Access Management", - "text": "Consider checking uploaded data, after clients used a SAS to upload a file. ", - "waf": "Security" + "subcategory": "VM", + "text": "containerizing an application can improve VM density and save money on scaling it", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "When accessing blob storage via SFTP using a 'local user account', the 'usual' RBAC controls do not apply. Blob access via NFS or REST might be more restrictive than SFTP access. Unfortunately, as of early 2023, local users are the only form of identity management that is currently supported for the SFTP endpoint", - "guid": "ad53cc7c-e1d7-4aaa-a357-1449ab8053d8", - "id": "A15.06", - "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-support#sftp-permission-model", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "d7e47431-76c8-4bdb-b55b-ce619e8a03f9", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/openshift/howto-create-service-principal?pivots=aro-azurecli", "services": [ "RBAC", - "Entra", - "Storage" + "Entra" ], "severity": "High", - "subcategory": "Identity and Access Management", - "text": "SFTP: Limit the amount of 'local users' for SFTP access, and audit whether access is needed over time.", + "subcategory": "Identity", + "text": "Create a service principal and its role assignments before creating the ARO clusters.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "guid": "9f89dc7b-33be-42a1-a27f-7b9e91be1f38", - "id": "A15.07", - "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-known-issues#authentication-and-authorization", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "7879424d-6267-486d-90b9-6c97be985190", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/openshift/configure-azure-ad-ui", "services": [ - "Entra", - "Storage" + "Entra" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "SFTP: The SFTP endpoint does not support POSIX-like ACLs.", + "severity": "High", + "subcategory": "Identity", + "text": "Use AAD to authenticate users in your ARO cluster.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Storage supports CORS (Cross-Origin Resource Sharing), i.e. an HTTP feature that enables web apps from a different domain to loosen the same-origin policy. When enabling CORS, keep the CorsRules to the least privilege.", - "guid": "cef39812-bd46-43cb-aac8-ac199ebb91a3", - "id": "A16.01", - "link": "https://learn.microsoft.com/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "adfec5f9-a82d-46e9-a8d1-5a0c7fed5d15", + "id": "A01.03", + "link": "https://docs.openshift.com/container-platform/4.14/authentication/remove-kubeadmin.html", "services": [ - "Storage", - "AzurePolicy" + "Entra" ], - "severity": "High", - "subcategory": "Networking", - "text": "Avoid overly broad CORS policies", + "subcategory": "Identity", + "text": "When using AAD authentication, remove kubeadmin user from the cluster.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Data at rest is always encrypted server-side, and in addition might be encrypted client-side as well. Server-side encryption might happen using a platform-managed key (default) or customer-managed key. Client-side encryption might happen by either having the client supply an encryption/decryption key on a per-blob basis to Azure storage, or by completely handling encryption on the client-side. thus not relying on Azure Storage at all for confidentiality guarantees.", - "guid": "3d90cae2-cc88-4137-86f7-c0cbafe61464", - "id": "A17.01", - "link": "https://learn.microsoft.com/azure/storage/common/storage-service-encryption", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "483835c9-86bb-4291-8155-a11475e39f54", + "id": "A01.04", + "link": "https://docs.openshift.com/container-platform/4.13/applications/projects/working-with-projects.html", "services": [ - "Storage" + "RBAC", + "Entra" ], "severity": "High", - "subcategory": "Confidentiality and Encryption", - "text": "Determine how data at rest should be encrypted. Understand the thread model for data.", + "subcategory": "Identity", + "text": "Define OpenShift projects to restrict RBAC privilege and isolate workloads in your cluster.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "guid": "8dd457e9-2713-48b8-8110-2cac6eae01e6", - "id": "A17.02", - "link": "https://learn.microsoft.com/azure/storage/common/customer-managed-keys-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&bc=%2Fazure%2Fstorage%2Fblobs%2Fbreadcrumb%2Ftoc.json", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "0acccd97-9376-4bcd-a375-0ab2ab039da6", + "id": "A01.05", + "link": "https://docs.openshift.com/container-platform/4.13/authentication/using-rbac.html", "services": [ - "Storage" + "RBAC", + "Entra" ], "severity": "Medium", - "subcategory": "Confidentiality and Encryption", - "text": "Determine which/if platform encryption should be used.", + "subcategory": "Identity", + "text": "Define the required RBAC roles in OpenShift are scoped to either a project or a cluster.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "guid": "e842e52f-4721-4d92-ac1b-1cd521e54a29", - "id": "A17.03", - "link": "https://learn.microsoft.com/azure/storage/blobs/encryption-customer-provided-keys", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "d54d7c89-29db-4107-b532-5ae625ca44e4", + "id": "A01.06", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "services": [ - "Storage" + "AKV", + "Entra" ], "severity": "Medium", - "subcategory": "Confidentiality and Encryption", - "text": "Determine which/if client-side encryption should be used.", + "subcategory": "Identity", + "text": "Minimize the number of users who have administrator rights and secrets access.", "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Blob Storage Review", - "description": "Leverage Resource Graph Explorer (resources | where type == 'microsoft.storage/storageaccounts' | where properties['allowBlobPublicAccess'] == true) to find storage accounts which allow anonymous blob access.", - "guid": "659ae558-b937-4d49-a5e1-112dbd7ba012", - "id": "A18.01", - "link": "https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-configure?tabs=portal#allow-or-disallow-public-read-access-for-a-storage-account", + "category": "Identity and Access Management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "685e2223-ace8-4bb1-8307-ca5f16f154e3", + "id": "A01.07", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "Entra", - "Storage" + "RBAC", + "Entra" ], - "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Consider whether public blob access is needed, or whether it can be disabled for certain storage accounts. ", + "severity": "Medium", + "subcategory": "Identity", + "text": "Use Privileged Identity Management in AAD for ARO users with privileged roles.", "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "a95b86ad-8840-48e3-9273-4b875ba18f20", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "aa369282-9e7e-4216-8836-87af467a1f89", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "services": [ - "Monitor", - "Cost" + "VNet", + "WAF", + "Entra", + "Subscriptions", + "Firewall", + "DDoS" ], - "subcategory": "Azure Monitor - enforce data collection rules", - "text": "Data collection rules in Azure Monitor -https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-rule-overview", - "training": "https://azure.microsoft.com/pricing/reservations/" + "severity": "Low", + "subcategory": "DDoS", + "text": "Use Azure DDoS Network/IP Protection to protect the virtual network you use for the ARO cluster unless you use Azure Firewall or WAF in a centralized subscription", + "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "45901365-d38e-443f-abcb-d868266abca2", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", - "services": [ - "Backup", - "Cost" - ], - "subcategory": "Backup", - "text": "check backup instances with the underlying datasource not found" + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "35bda433-24f1-4481-8533-182aa5174269", + "id": "B02.01", + "link": "https://docs.openshift.com/container-platform/4.13/networking/routes/secured-routes.html", + "services": [], + "severity": "High", + "subcategory": "Encryption", + "text": "All web applications you configure to use an ingress should use TLS encryption and shouldn't allow access over unencrypted HTTP.", + "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "64f9a19a-f29c-495d-94c6-c7919ca0f6c5", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "44008ae7-d7e4-4743-876c-8bdbf55bce61", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", "services": [ - "Cost" + "WAF", + "FrontDoor" ], - "subcategory": "delete/archive", - "text": "delete or archive unassociated services (disks, nics, ip addresses etc)" + "severity": "Medium", + "subcategory": "Internet", + "text": "Use Azure Front Door with WAF to securely publish ARO applications to the internet, especially in multi-region environments.", + "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "659d3958-fd77-4289-a835-556df2bfe456", - "id": "A03.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "9e8a03f9-7879-4424-b626-786d60b96c97", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/openshift/howto-secure-openshift-with-front-door", "services": [ - "Cost" + "FrontDoor", + "PrivateLink" ], - "subcategory": "delete/archive", - "text": "consider snooze and stop technique (snooze a service after x days, stop after 2x, delete/deallocate after 3x)" + "severity": "Medium", + "subcategory": "Internet", + "text": "If exposing an app on ARO with Azure Front Door, use private link to connect Front Door with the ARO router.", + "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "3b0d834a-3487-426d-b69c-6b5c2a26494b", - "id": "A03.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "be985190-4838-435c-a86b-b2912155a114", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/openshift/howto-restrict-egress", "services": [ - "Backup", - "Storage", - "Cost" + "Firewall", + "NVA", + "AzurePolicy" ], - "subcategory": "delete/archive", - "text": "delete or archive unused resources (old backups, logs, storage accounts, etc...)" + "severity": "Medium", + "subcategory": "Internet", + "text": "If your security policy requires you to inspect all outbound internet traffic that's generated in the ARO cluster, secure egress network traffic by using Azure Firewall or an NVA.", + "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "69bad37a-ad53-4cc7-ae1d-76667357c449", - "id": "A03.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "75e39f54-0acc-4cd9-9937-6bcda3750ab2", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/openshift/howto-create-private-cluster-4x", "services": [ - "Backup", - "ASR", - "Storage", - "Cost" + "AzurePolicy" ], - "subcategory": "delete/archive", - "text": "consider a good balance between site recovery storage and backup for non mission critical applications" + "severity": "High", + "subcategory": "Private access", + "text": "If your security policy requires you to use a private IP address for the OpenShift API, deploy a private ARO cluster.", + "waf": "Security" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "674b5ed8-5a85-49c7-933b-e2a1a27b765a", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "category": "Network topology and connectivity", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "ab039da6-d54d-47c8-a29d-b107d5325ae6", + "id": "B04.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", "services": [ - "Monitor", - "Cost" + "ACR", + "PrivateLink" ], - "subcategory": "Log Analytics retention for workspaces", - "text": "check spending and savings opportunities among the 40 different log analytics workspaces- use different retention and data collection for nonprod workspaces-create daily cap for awareness and tier sizing - If you do set a daily cap, in addition to creating an alert when the cap is reached,ensure that you also create an alert rule to be notified when some percentage has been reached (90% for example). - consider workspace transformation if possible - https://learn.microsoft.com/azure/azure-monitor/essentials/data-collection-transformations#workspace-transformation-dcr ", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/understand-work-scopes" - }, + "severity": "Medium", + "subcategory": "Private access", + "text": "Use Azure Private Link to secure network connections to managed Azure services, including to Azure Container Registry.", + "waf": "Security" + }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "91be1f38-8ef3-494c-8bd4-63cbbac75819", - "id": "A05.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "25ca44e4-685e-4222-9ace-8bb12307ca5f", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-enable-arc-enabled-clusters", "services": [ - "Storage", - "AzurePolicy", - "Cost" + "Monitor" ], - "subcategory": "Policy", - "text": "enforce a purging log policy and automation (if needed, logs can be moved to cold storage)", - "training": "https://www.youtube.com/watch?v=nHQYcYGKuyw" + "severity": "High", + "subcategory": "Operations", + "text": "Establish a monitoring process using the inbuilt Prometheus, OpenShift Logging or Container Insights integration.", + "waf": "Operations" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "59bb91a3-ed90-4cae-8cc8-4c37b6b780cb", - "id": "A06.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", - "services": [ - "Cost" - ], - "subcategory": "run orphaned resources workbook - delete or snooze ghost items", - "text": "https://github.com/dolevshor/azure-orphan-resources", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "16f154e3-aa36-4928-89e7-e216183687af", + "id": "C01.02", + "link": "https://docs.openshift.com/container-platform/4.13/cicd/pipelines/understanding-openshift-pipelines.html", + "services": [], + "severity": "Medium", + "subcategory": "Operations", + "text": "Automate the application delivery process through DevOps practices and CI/CD solutions, such as Pipelines/GitOps provided by OpenShift.", + "waf": "Operations" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "9fe5c464-89d4-457a-a27c-3874d0102cac", - "id": "A07.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", - "services": [ - "Cost" - ], - "subcategory": "shutdown/deallocate", - "text": "shutdown underutilized instances", - "training": "https://learn.microsoft.com/azure/cost-management-billing/understand/analyze-unexpected-charges" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "467a1f89-35bd-4a43-924f-14811533182a", + "id": "C01.03", + "link": "https://learn.microsoft.com/azure/architecture/guide/design-principles/managed-services", + "services": [], + "severity": "Low", + "subcategory": "Operations", + "text": "Whenever possible, remove the service state from inside containers. Instead, use an Azure platform as a service (PaaS) that supports multiregion replication.", + "waf": "Operations" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "6aae01e6-a84d-4e5d-b36d-1d92881a1bd5", - "id": "A08.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "1b7da8cf-aa66-4e15-b4d5-ada97dc3e232", + "id": "C01.04", + "link": "https://learn.microsoft.com/azure/openshift/howto-create-a-storageclass", "services": [ - "VM", - "Backup", - "Storage", - "Cost" + "Storage" ], - "subcategory": "stopped/deallocated VMs: check disks", - "text": "check that the disks are really needed, if not: delete. If they are needed, find lower storage tiers or use backup -", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/manage-automation" + "severity": "Low", + "subcategory": "Operations", + "text": "Use RWX storage with inbuilt Azure Files storage class.", + "waf": "Operations" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "d1e44a19-659d-4395-afd7-7289b835556d", - "id": "A09.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", - "services": [ - "Storage", - "AzurePolicy", - "Cost" - ], - "subcategory": "storage accounts lifecycle policy", - "text": "consider moving unused storage to lower tier, with customized rule - https://learn.microsoft.com/azure/storage/blobs/lifecycle-management-policy-configure ", - "training": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "6bb235c7-05e1-4696-bded-fa8a4c8cdec4", + "id": "C02.01", + "link": "https://docs.openshift.com/container-platform/4.13/nodes/clusters/nodes-cluster-limit-ranges.html", + "services": [], + "severity": "Medium", + "subcategory": "Performance", + "text": "Use pod requests and limits to manage the compute resources within a cluster.", + "waf": "Performance" }, { - "category": "Cleanup", - "checklist": "Cost Optimization Checklist", - "guid": "f2bfe456-3b0d-4834-a348-726de69c6b5c", - "id": "A10.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", - "services": [ - "Cost" - ], - "subcategory": "Tagging", - "text": "use specific tags for temporary items with 'delete by DATE' format - and automate monthly cleanup" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "c620c30c-14ee-4b7f-9ae8-d9b3fec228e7", + "id": "C02.02", + "link": "https://docs.openshift.com/container-platform/4.13/applications/quotas/quotas-setting-per-project.html", + "services": [], + "severity": "Medium", + "subcategory": "Performance", + "text": "Enforce resource quotas on projects.", + "waf": "Performance" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "2a26494b-69ba-4d37-aad5-3cc78e1d7666", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", - "services": [ - "Cost" - ], - "subcategory": "db optimization", - "text": "plan for db optimization with the intent of downsizing the related services (and improve performance)" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "87ab177a-db59-4f6b-a613-334fd09dc234", + "id": "C02.03", + "link": "https://docs.openshift.com/container-platform/4.13/machine_management/applying-autoscaling.html", + "services": [], + "severity": "High", + "subcategory": "Performance", + "text": "Define ClusterAutoScaler and MachineAutoScaler to scale machines when your cluster runs out of resources to support more deployments.", + "waf": "Performance" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "7357c449-674b-45ed-a5a8-59c7733be2a1", - "id": "B02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "19db6128-1269-4040-a4ba-4d3e0804276d", + "id": "C03.01", + "link": "https://learn.microsoft.com/azure/openshift/support-policies-v4#supported-virtual-machine-sizes", "services": [ - "Cost" + "VM" ], - "subcategory": "app modernization", - "text": "modernizing the app towards a microservices architecture will have the effect of letting the app scale according to the single service and not the entire stack" + "severity": "High", + "subcategory": "Reliability", + "text": "Use virtual machine sizes that are large enough to contain multiple container instances so you get the benefits of increased density, but not so large that your cluster can't handle the workload of a failing node.", + "waf": "Reliability" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "a27b765a-91be-41f3-a8ef-394c2bd463cb", - "id": "B03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", - "services": [ - "VM", - "Storage", - "Cost" - ], - "subcategory": "db optimization", - "text": "optimizing the DB queries will increase performance and allow better right-sizing of storage and VMs" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "4b98b15c-8b31-4aa5-aceb-58889135e227", + "id": "C03.02", + "link": "https://docs.openshift.com/container-platform/4.13/machine_management/deploying-machine-health-checks.html", + "services": [], + "severity": "High", + "subcategory": "Reliability", + "text": "Deploy machine health checks to automatically repair damaged machines in a machine pool.", + "waf": "Reliability" }, { - "category": "DB/APP tuning", - "checklist": "Cost Optimization Checklist", - "guid": "bac75819-59bb-491a-9ed9-0cae2cc84c37", - "id": "B04.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "896d31b6-6c67-4ba5-a119-c08e8f5d587c", + "id": "C03.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-metric-alerts", "services": [ - "Cost" + "Monitor" ], - "subcategory": "demand shaping", - "text": "using demand shaping on PaaS services will optimize costs and performances" + "severity": "High", + "subcategory": "Reliability", + "text": "Use an alerting system to provide notifications when things need direct action: Container Insights metric alerts or in-built Alerting UI.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "b6b780cb-9fe5-4c46-989d-457a927c3874", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", - "services": [ - "Entra", - "Cost" - ], - "subcategory": "Advisor", - "text": "Start from the Azure Advisor page suggestions." + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "7e9ced16-acd1-476e-b9b2-41a998a57ae7", + "id": "C03.04", + "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview#availability-zones", + "services": [], + "severity": "High", + "subcategory": "Reliability", + "text": "Ensure that the cluster is created in a region that supports AZs and create a machine set for each AZ.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "d0102cac-6aae-401e-9a84-de5de36d1d92", - "id": "C01.02", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "7b997e71-1b7d-4a8c-baa6-6e15d4d5ada9", + "id": "C03.05", + "link": "https://docs.openshift.com/container-platform/4.13/machine_management/creating-infrastructure-machinesets.html", "services": [ - "VM", - "Cost" + "AKS" ], - "subcategory": "Advisor", - "text": "make sure advisor is configured for VM right sizing " + "severity": "Low", + "subcategory": "Reliability", + "text": "Create infrastructure machine sets to hold infrastructure components. Apply specific Kubernetes labels to these machines and then update the infrastructure components to run on only those machines.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "881a1bd5-d1e4-44a1-a659-d3958fd77289", - "id": "C02.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [ - "Cost" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "7dc3e232-6bb2-435c-905e-1696fdedfa8a", + "id": "C03.06", + "link": "https://learn.microsoft.com/azure/openshift/howto-create-a-backup#create-a-backup-with-velero-to-include-snapshots", + "services": [ + "Backup" ], - "subcategory": "Automation", - "text": "consider implementing IAC scripts or devops pipelines to match the cost governance process" + "severity": "Medium", + "subcategory": "Reliability", + "text": "Create application backup and plan for restore and include persistent volumes in the backup.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "b835556d-f2bf-4e45-93b0-d834a348726d", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [ - "Monitor", - "Cost" - ], - "subcategory": "Automation", - "text": "set up cost alerts for applications that have variable costs (ideally for all of them)" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "81c12318-1a64-4174-8583-3fb4ae3c2df7", + "id": "C03.07", + "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-priority.html", + "services": [], + "severity": "Low", + "subcategory": "Reliability", + "text": "Use pod priorities, so that in case of limited resources the most critical pods will run.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "e69c6b5c-2a26-4494-a69b-ad37aad53cc7", - "id": "C02.03", - "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "43166c3b-cbe0-45bb-b209-d4a0da577784", + "id": "C04.01", + "link": "https://docs.openshift.com/container-platform/4.13/architecture/admission-plug-ins.html", "services": [ - "Cost" + "AzurePolicy" ], - "subcategory": "Automation", - "text": "Use Azure Automation: Automate repetitive tasks can help you save time and resources, reducing costs in the process. " + "severity": "Low", + "subcategory": "Security", + "text": "Regulate cluster functions using admission plug-ins, which are commonly used to enforce security policy, resource limitations, or configuration requirements.", + "waf": "Security" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "8e1d7666-7357-4c44-a674-b5ed85a859c7", - "id": "C02.04", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "24d21678-5d2f-4a56-a56a-d48408fe8273", + "id": "C04.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-geo-replication", "services": [ - "Cost" + "ACR" ], - "subcategory": "Automation", - "text": "run orphaned resources workbook" + "severity": "Low", + "subcategory": "Security", + "text": "Store your container images in Azure Container Registry and geo-replicate the registry to each region.", + "waf": "Security" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "733be2a1-a27b-4765-a91b-e1f388ef394c", - "id": "C03.01", - "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Baseline", - "text": "try and establish a baseline of monthly spending and an acceptable saving target against the baseline (new services will not be optimized at this stage)" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "4c486ba2-80dc-4059-8cf7-5ee8e1309ccc", + "id": "C05.01", + "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-vertical-autoscaler.html", + "services": [], + "severity": "Medium", + "subcategory": "Workload", + "text": "Optimize the CPU and memory request values, and maximize the efficiency of the cluster resources using vertical pod autoscaler.", + "waf": "Performance" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "2bd463cb-bac7-4581-a59b-b91a3ed90cae", - "id": "C03.02", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "d579366b-cda2-4750-aa1a-bfe9d55d14c3", + "id": "C05.02", + "link": "https://docs.openshift.com/container-platform/4.13/applications/application-health.html", "services": [ - "AzurePolicy", - "Cost" + "Monitor" ], - "subcategory": "Baseline", - "text": "establish a cost optimization baseline by using a policy that tags every new resource as #NEW" + "severity": "Medium", + "subcategory": "Workload", + "text": "Add health probes to your pods to monitor application health. Make sure pods contain livenessProbe and readinessProbe. Use Startup probes to determine the point at which the application has started up.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "2cc84c37-b6b7-480c-a9fe-5c46489d457a", - "id": "C03.03", - "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", - "services": [ - "Cost" - ], - "subcategory": "Baseline", - "text": "Organize resources to maximize cost insights and accountability" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "c4929cb1-b3d1-4325-ae12-4ba34d0685ed", + "id": "C05.03", + "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-autoscaling.html", + "services": [], + "severity": "Medium", + "subcategory": "Workload", + "text": "Scale pods to meet demand using horizontal pod autoscaler.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "927c3874-d010-42ca-a6aa-e01e6a84de5d", - "id": "C04.01", - "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "dce9be3b-b0dd-4b3b-95fb-2ec14eeaa359", + "id": "C05.04", + "link": "https://docs.openshift.com/container-platform/4.13/nodes/pods/nodes-pods-configuring.html#nodes-pods-pod-distruption-about_nodes-pods-configuring", "services": [ "Cost" ], - "subcategory": "Budgets", - "text": "Create budgets" + "severity": "Medium", + "subcategory": "Workload", + "text": "Use disruption budgets to ensure the required number of pod replicas exist to handle expected application load.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "e36d1d92-881a-41bd-9d1e-44a19659d395", - "id": "C05.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", - "services": [ - "Cost" - ], - "subcategory": "Cost Analysis", - "text": "in cost analysis - use daily granularity, grouped by service name to analyze the spending of the past 3 months and identify the top 3 spenders" + "category": "Operations management", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "2829e2ed-b217-4367-9aff-6791b4935ada", + "id": "C05.05", + "link": "https://docs.openshift.com/container-platform/4.13/nodes/scheduling/nodes-scheduler-pod-topology-spread-constraints.html", + "services": [], + "severity": "Medium", + "subcategory": "Workload", + "text": "Use pod topology constraints to automatically schedule pods on nodes throughout the cluster.", + "waf": "Reliability" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "8fd77289-b835-4556-bf2b-fe4563b0d834", - "id": "C05.02", - "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", - "services": [ - "Cost" - ], - "subcategory": "Cost Analysis", - "text": "check daily for cost spikes and anomalies (ideally with automatic billing exports)" + "category": "Platform Automation", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "42324ece-81c1-4231-a1a6-417415833fb4", + "id": "D01.01", + "link": "https://docs.openshift.com/container-platform/4.13/applications/deployments/route-based-deployment-strategies.html", + "services": [], + "severity": "Low", + "subcategory": "Workload", + "text": "Consider blue/green or canary strategies to deploy new releases of application.", + "waf": "Operations" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "a348726d-e69c-46b5-a2a2-6494b69bad37", - "id": "C05.03", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", - "services": [ - "Cost" - ], - "subcategory": "Cost Analysis", - "text": "automate cost retrieval for deep analysis or integration" + "category": "Platform Automation", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "ae3c2df7-4316-46c3-acbe-05bbe209d4a0", + "id": "D01.02", + "link": "https://docs.openshift.com/container-platform/4.13/cicd/gitops/understanding-openshift-gitops.html", + "services": [], + "severity": "Low", + "subcategory": "Workload", + "text": "Consider using Red Hat OpenShift GitOps. Red Hat OpenShift GitOps uses Argo CD to maintain cluster resources and support application CI/CD.", + "waf": "Operations" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "aad53cc7-8e1d-4766-9735-7c449674b5ed", - "id": "C06.01", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", - "services": [ - "ACR", - "Cost" - ], - "subcategory": "free services", - "text": "Take advantage of Azure free services: Azure offers a number of free services, such as DevOps, Azure Container Registry, and Azure Logic Apps, that can help you save costs on development and operations. " + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "da577784-24d2-4167-a5d2-fa56c56ad484", + "id": "E01.01", + "link": "https://learn.microsoft.com/azure/openshift/support-lifecycle", + "services": [], + "severity": "High", + "subcategory": "Control plane", + "text": "Keep your clusters on the latest OpenShift version to avoid potential security or upgrade issues.", + "waf": "Security" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "96c96ad8-844c-4f3b-8b38-c886ba2c0214", - "id": "C07.01", - "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "08fe8273-4c48-46ba-880d-c0591cf75ee8", + "id": "E01.02", + "link": "https://learn.microsoft.com/azure/azure-arc/kubernetes/quickstart-connect-cluster", "services": [ - "Cost" + "AKS", + "Arc" ], - "subcategory": "Tagging", - "text": "Tag shared resources" + "severity": "High", + "subcategory": "Control plane", + "text": "Connect Azure Red Hat OpenShift clusters to Azure Arc-enabled Kubernetes.", + "waf": "Security" }, { - "category": "Process Administration", - "checklist": "Cost Optimization Checklist", - "guid": "99014a5d-3ce5-474d-acbd-9792a6bcca2b", - "id": "C07.02", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", - "services": [ - "Cost" - ], - "subcategory": "Tagging", - "text": "consider using tags to all services for cost allocation" + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "e1309ccc-d579-4366-acda-2750aa1abfe9", + "id": "E02.01", + "link": "https://docs.openshift.com/container-platform/4.10/security/encrypting-etcd.html", + "services": [], + "severity": "Low", + "subcategory": "Encryption", + "text": "For Azure Red Hat OpenShift 4 clusters, etcd data isn't encrypted by default, but it's recommended to enable etcd encryption to provide another layer of data security.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "4fea1dbf-3dd9-45d4-ac7c-891dcb1f7d57", - "id": "D01.01", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "d55d14c3-c492-49cb-8b3d-1325ae124ba3", + "id": "E03.01", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", "services": [ - "Cost" + "AKS", + "Defender", + "Arc" ], - "subcategory": "automation", - "text": "consider Reservation automation to track and promptly react to changes" + "severity": "Medium", + "subcategory": "Posture", + "text": "Use Microsoft Defender for Containers supported via Arc-enabled Kubernetes to secure clusters, containers, and applications.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "description": "check by searching the Meter Category Licenses in the Cost analysys", - "guid": "59ae568b-a38d-4498-9e22-13dbd7bb012f", - "id": "D02.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "4d0685ed-dce9-4be3-ab0d-db3b55fb2ec1", + "id": "E04.01", + "link": "https://learn.microsoft.com/azure/azure-arc/kubernetes/tutorial-akv-secrets-provider", "services": [ - "VM", - "SQL", - "AzurePolicy", - "Cost" + "AKS", + "AKV", + "Arc" ], - "subcategory": "check AHUB is applied to all Windows VMs, RHEL and SQL", - "text": "run the script on all windows VMs https://learn.microsoft.com/azure/virtual-machines/windows/hybrid-use-benefit-licensing?ref=andrewmatveychuk.com#convert-an-existing-vm-using-azure-hybrid-benefit-for-windows-server- consider implementing a policy if windows VMs are created frequently" + "severity": "Medium", + "subcategory": "Secrets", + "text": "For applications that require access to sensitive information, use a service principal and the AKV Secrets Provider with the extension for Arc-enabled Kubernetes clusters.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "7b95e06e-158e-42ea-9992-c2de6e2065b3", - "id": "D03.01", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", - "services": [ - "LoadBalancer", - "Cost" - ], - "subcategory": "check Red Hat Licences if applicable", - "text": " this can be also put under AHUB if you already have licenses https://learn.microsoft.com/azure/virtual-machines/linux/azure-hybrid-benefit-linux?tabs=rhelpayg%2Crhelbyos%2CrhelEnablebyos%2Crhelcompliance" + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "4eeaa359-2829-4e2e-bb21-73676aff6791", + "id": "E05.01", + "link": "https://learn.microsoft.com/azure/aks/developer-best-practices-pod-security#secure-pod-access-to-resources", + "services": [], + "severity": "Medium", + "subcategory": "Workload", + "text": "Secure pod access to resources. Provide the least number of permissions, and avoid using root or privileged escalation.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "a76af4a6-91e8-4839-ada4-6667e13c1056", - "id": "D04.01", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts", + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "b4935ada-4232-44ec-b81c-123181a64174", + "id": "E05.02", + "link": "https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes#install-azure-policy-extension-for-azure-arc-enabled-kubernetes", "services": [ - "AppSvc", - "Cost" + "Monitor", + "AzurePolicy" ], - "subcategory": "Functions", - "text": "saving plans will provide 17% on select app service plans" + "severity": "Medium", + "subcategory": "Workload", + "text": "Monitor and enforce configuration by using the Azure Policy Extension.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "75c1e945-b459-4837-bf7a-e7c6d3b475a5", - "id": "D05.01", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "15833fb4-ae3c-42df-9431-66c3bcbe05bb", + "id": "E05.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", "services": [ - "VM", - "Cost" + "Defender" ], - "subcategory": "planning", - "text": "consolidate reserved VM families with flexibility option (no more than 4-5 families)", - "training": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management" + "severity": "High", + "subcategory": "Workload", + "text": "Scan your images for vulnerabilities with Microsoft Defender or any other image scanning solution.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "c7acbe49-bbe6-44dd-a9f2-e87778468d55", - "id": "D06.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", + "category": "Security", + "checklist": "Use the 'Import latest checklist' button to get the latest version of a review checklist", + "guid": "e209d4a0-da57-4778-924d-216785d2fa56", + "id": "E05.04", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", "services": [ - "VM", - "ARS", - "Cost" + "Subscriptions", + "ACR" ], - "subcategory": "reservations/savings plans", - "text": "Utilize Azure Reserved Instances: This feature allows you to reserve VMs for a period of 1 or 3 years, providing significant cost savings compared to PAYG prices." + "severity": "Low", + "subcategory": "Workload", + "text": "Deploy a dedicated and private instance of Azure Container Registry to each landing zone subscription.", + "waf": "Security" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "a785c6fe-96c9-46ad-a844-cf3b2b38c886", - "id": "D06.02", - "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations", "services": [ - "Cost" + "Entra" ], - "subcategory": "reservations/savings plans", - "text": "plan for Azure Savings Plans for all the workloads that are dynamic and need maximum flexibility" + "severity": "Medium", + "subcategory": "Microsoft Entra ID Tenants", + "text": "Use one Entra tenant for managing your Azure resources, unless you have a clear regulatory or business requirement for multi-tenants.", + "waf": "Operations" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "ba2c0214-9901-44a5-b3ce-574dccbd9792", - "id": "D06.03", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", "services": [ - "Cost" + "Entra" ], - "subcategory": "reservations/savings plans", - "text": "plan for Azure Reservations for all the workloads that are less dynamic and won't change much" + "severity": "Low", + "subcategory": "Microsoft Entra ID Tenants", + "text": "Ensure you have a Multi-Tenant Automation approach to managing your Microsoft Entra ID Tenants", + "waf": "Operations" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "a6bcca2b-4fea-41db-b3dd-95d48c7c891d", - "id": "D07.01", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", "services": [ - "Storage", - "Cost" + "Entra" ], - "subcategory": "reserve storage", - "text": "only larger disks can be reserved =>1TiB -" + "severity": "Low", + "subcategory": "Microsoft Entra ID Tenants", + "text": "Leverage Azure Lighthouse for Multi-Tenant Management", + "waf": "Operations" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "cb1f7d57-59ae-4568-aa38-d4985e2213db", - "id": "D08.01", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "VM", - "Cost" + "Entra" ], - "subcategory": "reserve VMs with normalized and rationalized sizes", - "text": "after the right-sizing optimization" + "severity": "Medium", + "subcategory": "Cloud Solution Provider", + "text": "Ensure that Azure Lighthouse is used for administering the tenant by partner", + "waf": "Cost" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "d7bb012f-7b95-4e06-b158-e2ea3992c2de", - "id": "D09.01", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "SQL", - "AzurePolicy", - "Cost" + "Entra" ], - "subcategory": "SQL Database AHUB", - "text": "check if applicable and enforce policy/change https://learn.microsoft.com/azure/azure-sql/azure-hybrid-benefit?view=azuresql&tabs=azure-portalhttps://learn.microsoft.com/azure/cost-management-billing/scope-level/create-sql-license-assignments?source=recommendations" + "severity": "Low", + "subcategory": "Cloud Solution Provider", + "text": "Discuss support request and escalation process with CSP partner", + "waf": "Cost" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "6e2065b3-a76a-4f4a-991e-8839ada46667", - "id": "D10.01", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "32952499-58c8-4e6f-ada5-972e67893d55", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "VM", - "SQL", - "Cost" + "Cost", + "Entra" ], - "subcategory": "SQL Database Reservations", - "text": "the VM + licence part discount (ahub+3YRI) is around 70% discount" + "severity": "Medium", + "subcategory": "Cloud Solution Provider", + "text": "Setup Cost Reporting and Views with Azure Cost Management", + "waf": "Cost" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "e13c1056-75c1-4e94-9b45-9837ff7ae7c6", - "id": "D11.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "services": [ - "Cost" + "LoadBalancer", + "Entra" ], - "subcategory": "tracking", - "text": "Make sure you Azure Reservations and Savings plans are close to 100% utilization or make the necessary changes to reach it." + "severity": "Medium", + "subcategory": "Enterprise Agreement", + "text": "Configure Notification Contacts to a group mailbox", + "waf": "Cost" }, { - "category": "reservations", - "checklist": "Cost Optimization Checklist", - "guid": "d3b475a5-c7ac-4be4-abbe-64dd89f2e877", - "id": "D11.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "AzurePolicy", - "Cost" + "TrafficManager", + "Entra" ], - "subcategory": "tracking", - "text": "make sure that your reservations usage is close to 100%. If not, either enforce an allowed SKU policy or exchange the reservation" + "severity": "Low", + "subcategory": "Enterprise Agreement", + "text": "Use departments and accounts to map your organization's structure to your enrollment hierarchy which can help with separating billing.", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "78468d55-a785-4c6f-b96c-96ad8844cf3b", - "id": "E01.01", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "ammp": true, + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "AzurePolicy", - "Cost" + "Entra" ], - "subcategory": "Automation", - "text": "plan and enforce a ON/OFF policy for production services, where possible" + "severity": "High", + "subcategory": "Enterprise Agreement", + "text": "Ensure that Accounts are configured to be of the type 'Work or School Account", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "2b38c886-ba2c-4021-9990-14a5d3ce574d", - "id": "E01.02", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "AzurePolicy", - "Cost" + "Cost", + "Entra" ], - "subcategory": "Automation", - "text": "plan and enforce a ON-DEMAND policy with auto-shutdown for non-production services, where possible" + "severity": "Medium", + "subcategory": "Enterprise Agreement", + "text": "Enable both DA View Charges and AO View Charges on your EA Enrollments to allow users with the correct perms review Cost and Billing Data.", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "ccbd9792-a6bc-4ca2-a4fe-a1dbf3dd95d4", - "id": "E02.01", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "VM", - "Cost" + "Subscriptions", + "Cost", + "Entra" ], - "subcategory": "Autoscale", - "text": "consider using a VMSS to match demand rather than flat sizing" + "severity": "Low", + "subcategory": "Enterprise Agreement", + "text": "Make use of Enterprise Dev/Test Subscriptions to reduce costs for non-production workloads", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "c1b1cd52-1e54-4a29-a9de-39ac0e7c28dc", - "id": "E02.02", - "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "services": [ - "AKS", - "Cost" + "RBAC", + "Entra" ], - "subcategory": "Autoscale", - "text": "use AKS autoscaler to match your clusters usage (make sure the pods requirements match the scaler)" + "severity": "Medium", + "subcategory": "Enterprise Agreement", + "text": "Periodically audit the role assignments to review who has access to your Enterprise Agreement Enrollment", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "93665720-2bff-4456-9b0d-934a359c363e", - "id": "E02.03", - "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Cost" + "Entra" ], - "subcategory": "Autoscale", - "text": "right-size PaaS service according to average use and accomodate spikes with auto or manual scaling" + "severity": "Low", + "subcategory": "Microsoft Customer Agreement", + "text": "Configure Agreement billing account notification contact email", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "7dd61623-a364-4a90-9eba-e38ead53cc7d", - "id": "E02.04", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "services": [ - "Cost" + "Storage", + "Cost", + "Entra" ], - "subcategory": "Autoscale", - "text": "plan for demand shaping where applicable" + "severity": "Low", + "subcategory": "Microsoft Customer Agreement", + "text": "Use Billing Profiles and Invoice sections to structure your agreements billing for effective cost management", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "e2e8aaab-3571-4549-ab91-53d89f89dc7b", - "id": "E02.05", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Cost" + "Cost", + "Entra" ], - "subcategory": "Autoscale", - "text": "consider implementing a service re-scaling logic within the application", - "training": "https://learn.microsoft.com/azure/cost-management-billing/savings-plan/" + "severity": "Low", + "subcategory": "Microsoft Customer Agreement", + "text": "Make use of Azure Plan to reduce costs for non-production workloads", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "44be3b1a-27f8-4b9e-a1be-1f38df03a822", - "id": "E03.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", + "category": "Azure Billing and Microsoft Entra ID Tenants", + "checklist": "Azure Landing Zone Review", + "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "services": [ - "Backup", - "Cost" + "RBAC", + "Entra" ], - "subcategory": "Backup", - "text": "Move recovery points to vault-archive where applicable (Validate)", - "training": "https://azure.microsoft.com/pricing/reservations/" + "severity": "Medium", + "subcategory": "Microsoft Customer Agreement", + "text": "Periodically audit the agreement billing RBAC role assignments to review who has access to your MCA billing account", + "waf": "Cost" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "cd463cbb-bc8a-4c29-aebc-91a43da1dae2", - "id": "E04.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "ammp": true, + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "4348bf81-7573-4512-8f46-9061cc198fea", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", "services": [ - "VM", - "LoadBalancer", - "Cost" + "Entra" ], - "subcategory": "databricks", - "text": "consider using Spot VMs with fallback where possibleconsider autotermination of clusters https://learn.microsoft.com/azure/databricks/clusters/cluster-config-best-practices#automatic-termination ", - "training": "https://andrewmatveychuk.com/how-to-audit-azure-hybrid-benefit-usage-with-azure-workbooks/" + "severity": "High", + "subcategory": "Microsoft Entra ID and Hybrid Identity", + "text": "Use managed identities instead of service principals for authentication to Azure services", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "cc881470-607c-41cc-a0e6-14658dd458e9", - "id": "E05.01", - "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "services": [ - "Cost" + "Entra", + "ASR" ], - "subcategory": "Functions", - "text": "Functions - Reuse connections", - "training": "https://learn.microsoft.com/azure/cost-management-billing/reservations/reservation-apis?toc=%2Fazure%2Fcost-management-billing%2Ftoc.json" + "severity": "Medium", + "subcategory": "Microsoft Entra ID", + "text": "When deploying an AD Connect VM, consider having a staging sever for high availability / Disaster recovery", + "waf": "Reliability" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "27139b82-1102-4dbd-9eaf-11e6f843e52f", - "id": "E05.02", - "link": "https://learn.microsoft.com/azure/automation/update-management/overview", + "ammp": true, + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "984a859c-773e-47d2-9162-3a765a917e1f", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "services": [ - "Cost" + "Entra" ], - "subcategory": "Functions", - "text": "functions -Cache data locally", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/" - }, - { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "4722d928-c1b1-4cd5-81e5-4a29b9de39ac", - "id": "E05.03", - "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Functions", - "text": "functions - Cold starts-Use the 'Run from package' functionality. This way, the code is downloaded as a single zip file. This can, for example, result in significant improvements with Javascript functions, which have a lot of node modules.Use language specific tools to reduce the package size, for example, tree shaking Javascript applications.", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" + "severity": "High", + "subcategory": "Identity", + "text": "Implement an emergency access or break-glass accounts to prevent tenant-wide account lockout", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "0e7c28dc-9366-4572-82bf-f4564b0d934a", - "id": "E05.04", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "services": [ - "Cost" + "Monitor", + "Entra" ], - "subcategory": "Functions", - "text": "Functions -Keep your functions warm", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "severity": "Medium", + "subcategory": "Identity", + "text": "Integrate Microsoft Entra ID logs with the platform-central Azure Monitor. Azure Monitor allows for a single source of truth around log and monitoring data in Azure, giving organizations a cloud native options to meet requirements around log collection and retention.", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "359c363e-7dd6-4162-9a36-4a907ebae38e", - "id": "E05.05", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "ammp": true, + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "348ef254-c27d-442e-abba-c7571559ab91", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "services": [ - "Cost" + "Entra", + "Subscriptions", + "RBAC", + "ACR" ], - "subcategory": "Functions", - "text": "when using autoscale with different functions, there might be one driving all the autoscale for all the resources - consider moving it to a separate consumption plan (and consider higher plan for CPU)" + "severity": "High", + "subcategory": "Identity", + "text": "Enforce a RBAC model that aligns to your cloud operating model. Scope and Assign across Management Groups and Subscriptions.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "ad53cc7d-e2e8-4aaa-a357-1549ab9153d8", - "id": "E05.06", - "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "services": [ - "Cost" + "Entra", + "AzurePolicy" ], - "subcategory": "Functions", - "text": "Function apps in a given plan are all scaled together, so any issues with scaling can affect all apps in the plan." + "severity": "Low", + "subcategory": "Identity", + "text": "Enforce Microsoft Entra ID conditional-access policies for any user with rights to Azure environments", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "9f89dc7b-44be-43b1-a27f-8b9e91be1f38", - "id": "E05.07", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", + "ammp": true, + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", + "id": "B03.05", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "services": [ - "Cost" + "Entra" ], - "subcategory": "Functions", - "text": "Am I billed for 'await time' ?This question is typically asked in the context of a C# function that does an async operation and waits for the result, e.g. await Task.Delay(1000) or await client.GetAsync('http://google.com'). The answer is yes - the GB second calculation is based on the start and end time of the function and the memory usage over that period. What actually happens over that time in terms of CPU activity is not factored into the calculation.One exception to this rule is if you are using durable functions. You are not billed for time spent at awaits in orchestrator functions.apply demand shaping techinques where possible (dev environments?) https://github.com/Azure-Samples/functions-csharp-premium-scaler" + "severity": "High", + "subcategory": "Identity", + "text": "Enforce multi-factor authentication for any user with rights to the Azure environments", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "df03a822-cd46-43cb-abc8-ac299ebc91a4", - "id": "E06.01", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", + "id": "B03.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "services": [ - "Cost" + "RBAC", + "Entra" ], - "subcategory": "Networking", - "text": "evaluate your network topology against networking costs and where applicable reduce the egress and peering data" + "severity": "Medium", + "subcategory": "Identity", + "text": "Enforce centralized and delegated responsibilities to manage resources deployed inside the landing zone, based on role and security requirements", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "3da1dae2-cc88-4147-8607-c1cca0e61465", - "id": "E06.02", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "14658d35-58fd-4772-99b8-21112df27ee4", + "id": "B03.07", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "FrontDoor", - "EventHubs", - "Cost" + "Entra" ], - "subcategory": "Networking", - "text": "Frontdoor - Turn off the default homepageIn the application settings of your App, set AzureWebJobsDisableHomepage to true. This will return a 204 (No Content) to the PoP so only header data is returned." + "severity": "Medium", + "subcategory": "Identity", + "text": "Enforce Microsoft Entra ID Privileged Identity Management (PIM) to establish zero standing access and least privilege", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "8dd458e9-2713-49b8-8110-2dbd6eaf11e6", - "id": "E06.03", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", + "ammp": true, + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", + "id": "B03.08", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts", "services": [ - "AppSvc", - "FrontDoor", - "Cost" + "Entra" ], - "subcategory": "Networking", - "text": "Frontdoor -Route to something that returns nothingEither set up a Function, Function Proxy, or add a route in your WebApp that returns 200 (OK) and sends no or minimal content. The advantage of this is you will be able to log out when it is called." + "severity": "High", + "subcategory": "Identity", + "text": "Only use the authentication type Work or school account for all account types. Avoid using the Microsoft account", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "f843e52f-4722-4d92-ac1b-1cd521e54a29", - "id": "E07.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", + "id": "B03.09", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "services": [ - "Cost" + "Entra" ], - "subcategory": "PaaS", - "text": "consider using free tiers where applicable for all non-production environments" + "severity": "Medium", + "subcategory": "Identity", + "text": "Only use groups to assign permissions. Add on-premises groups to the Azure-AD-only group if a group management system is already in place.", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "b9de39ac-0e7c-428d-a936-657202bff456", - "id": "E08.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "f5664b5e-984a-4859-a773-e7d261623a76", + "id": "B03.10", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "services": [ - "Cost" + "Subscriptions", + "RBAC", + "Entra" ], - "subcategory": "serverless", - "text": "using serverless patterns for spikes can help keeping costs down" + "severity": "Medium", + "subcategory": "Identity", + "text": "Consider using Azure custom roles for the following key roles: Azure platform owner, network management, security operations, subscription owner, application owner", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "7e31c67d-68cf-46a6-8a11-94956d697dc3", - "id": "E09.01", - "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", + "id": "B03.11", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "services": [ - "Storage", - "Cost" + "Subscriptions", + "Entra" ], - "subcategory": "Storage", - "text": "consider archiving tiers for less used data" + "severity": "Medium", + "subcategory": "Identity", + "text": "If Azure Active Directory Domains Services (AADDS) is in use, deploy AADDS within the primary region because this service can only be projected into one subscription", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "a2ed27b2-d186-4f1a-8252-bddde68a487c", - "id": "E09.02", - "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", + "id": "B03.12", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "services": [ - "Storage", - "Cost" + "Entra" ], - "subcategory": "Storage", - "text": "check disk sizes where the size does not match the tier (i.e. A 513 GiB disk will pay a P30 (1TiB) and consider resizing" + "severity": "Medium", + "subcategory": "Identity", + "text": "If AADDS in use, evaluate the compatibility of all workloads", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "dec4861b-c3bc-410a-b77e-26e4d5a3bec2", - "id": "E09.03", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", + "id": "B03.13", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "services": [ - "Storage", - "Cost" + "Entra" ], - "subcategory": "Storage", - "text": "consider using standard SSD rather than Premium or Ultra where possible" + "severity": "Medium", + "subcategory": "Identity", + "text": "If AD on Windows server in use, are the resources in Azure using the correct domain controller?", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "c4e2436b-1336-4db5-9f17-960eee0bdf5c", - "id": "E09.04", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", + "id": "B03.14", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "services": [ - "Storage", - "Cost" + "VPN", + "Entra" ], - "subcategory": "Storage", - "text": "For storage accounts, make sure that the chosen tier is not adding up transaction charges (it might be cheaper to move to the next tier)" + "severity": "Medium", + "subcategory": "Identity", + "text": "Consider using Microsoft Entra ID Application Proxy as a VPN or reverse proxy replacement to give remote users secure and authenticated access to internal applications (hosted in the cloud or on-premises).", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "c2efc5d7-61d4-41d2-900b-b47a393a040f", - "id": "E09.05", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "35037e68-9349-4c15-b371-228514f4cdff", + "id": "B03.15", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", "services": [ - "ASR", - "Storage", - "Cost" + "RBAC", + "Entra" ], - "subcategory": "Storage", - "text": "for ASR, consider using Standard SSD disks if the RPO/RTO and replication throughput allow it" + "severity": "Medium", + "subcategory": "Identity", + "text": "Avoid using on-premises synced accounts for Microsoft Entra ID role assignments.", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "d3294798-b118-48b2-a5a4-6ceb544451e1", - "id": "E10.01", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "services": [ - "Storage", - "Cost" + "VNet", + "Entra" ], - "subcategory": "storage", - "text": "storage accounts: check hot tier and/or GRS necessary" + "severity": "Low", + "subcategory": "Landing zones", + "text": "Configure Identity (ADDS) network segmentation through the use of a virtual Network and peer back to the hub. Providing authentication inside application landing zone (legacy).", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "92d34429-3c76-4286-97a5-51c5b04e4f18", - "id": "E10.02", - "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", + "id": "B04.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "services": [ + "AKV", "Storage", - "Cost" + "Entra", + "ACR", + "RBAC" ], - "subcategory": "storage", - "text": "Disks -validate use of Premium SSD disks everywhere: for example, non-prod could swap to Standard SSD or On demand Premium SSD " + "severity": "Medium", + "subcategory": "Landing zones", + "text": "Use Azure RBAC to manage data plane access to resources, if possible. E.G - Data Operations across Key Vault, Storage Account and Database Services. ", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "54387e5c-ed12-46cd-832a-f5b2fc6998a5", - "id": "E11.01", - "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", + "category": "Identity and Access Management", + "checklist": "Azure Landing Zone Review", + "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", + "id": "B04.03", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "services": [ - "Monitor", - "EventHubs", - "Cost" + "Entra" ], - "subcategory": "Synapse", - "text": "Create budgets to manage costs and create alerts that automatically notify stakeholders of spending anomalies and overspending risks." + "severity": "Medium", + "subcategory": "Landing zones", + "text": "Use Microsoft Entra ID PIM access reviews to periodically validate resource entitlements.", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "35e33789-7e31-4c67-b68c-f6a62a119495", - "id": "E11.02", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability", - "services": [ - "Storage", - "Cost" - ], - "subcategory": "Synapse", - "text": "Export cost data to a storage account for additional data analysis." + "ammp": true, + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", + "services": [], + "severity": "High", + "subcategory": "Naming and tagging", + "text": "It is recommended to follow Microsoft Best Practice Naming Standards", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "6d697dc3-a2ed-427b-8d18-6f1a1252bddd", - "id": "E11.03", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "graph": "resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1)", + "guid": "2df27ee4-12e7-4f98-9f63-04722dd69c5b", + "id": "C02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "services": [ - "SQL", - "Cost" + "Subscriptions" ], - "subcategory": "Synapse", - "text": "Control costs for a dedicated SQL pool by pausing the resource when it is not in use." + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce reasonably flat management group hierarchy with no more than four levels.", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "e68a487c-dec4-4861-ac3b-c10ae77e26e4", - "id": "E11.04", - "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "667313b4-f566-44b5-b984-a859c773e7d2", + "id": "C02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "services": [ - "Cost" + "Subscriptions" ], - "subcategory": "Synapse", - "text": "Enable the serverless Apache Spark automatic pause feature and set your timeout value accordingly." + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce a sandbox management group to allow users to immediately experiment with Azure", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "d5a3bec2-c4e2-4436-a133-6db55f17960e", - "id": "E11.05", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", + "id": "C02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "services": [ - "Cost" + "Subscriptions", + "RBAC", + "AzurePolicy" ], - "subcategory": "Synapse", - "text": "Create multiple Apache Spark pool definitions of various sizes." + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce a platform management group under the root management group to support common platform policy and Azure role assignment", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "ee0bdf5c-c2ef-4c5d-961d-41d2500bb47a", - "id": "E11.06", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", + "id": "C02.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "services": [ - "Cost" + "ExpressRoute", + "Subscriptions", + "DNS", + "VWAN" ], - "subcategory": "Synapse", - "text": "Purchase Azure Synapse commit units (SCU) for one year with a pre-purchase plan to save on your Azure Synapse Analytics costs.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce a dedicated connectivity subscription in the Connectivity management group to host an Azure Virtual WAN hub, private Domain Name System (DNS), ExpressRoute circuit, and other networking resources.", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "393a040f-d329-4479-ab11-88b2c5a46ceb", - "id": "E12.01", - "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "graph": "resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1)", + "guid": "33b6b780-8b9f-4e5c-9104-9d403a923c34", + "id": "C02.05", + "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", "services": [ - "VM", - "Cost" + "Subscriptions" ], - "subcategory": "VM", - "text": "Use SPOT VMs for interruptible jobs: These are VMs that can be bid on and purchased at a discounted price, providing a cost-effective solution for non-critical workloads.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce no subscriptions are placed under the root management group", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "544451e1-92d3-4442-a3c7-628637a551c5", - "id": "E12.02", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", + "id": "C02.06", + "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "services": [ - "VM", - "Cost" + "Subscriptions", + "RBAC" ], - "subcategory": "VM", - "text": "right-sizing all VMs" + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce that only privileged users can operate management groups in the tenant by enabling Azure RBAC authorization in the management group hierarchy settings", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "b04e4f18-5438-47e5-aed1-26cd032af5b2", - "id": "E12.03", - "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", + "id": "C02.07", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "services": [ - "VM", - "Cost" + "Subscriptions" ], - "subcategory": "VM", - "text": "swap VM sized with normalized and most recent sizes", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce management groups under the root-level management group to represent the types of workloads, based on their security, compliance, connectivity, and feature needs.", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "fc6998a5-35e3-4378-a7e3-1c67d68cf6a6", - "id": "E12.04", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "ammp": true, + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "49b82111-2df2-47ee-912e-7f983f630472", + "id": "C02.08", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "services": [ + "Subscriptions", + "RBAC", + "Cost", + "AzurePolicy" + ], + "severity": "High", + "subcategory": "Subscriptions", + "text": "Enforce a process to make resource owners aware of their roles and responsibilities, access review, budget review, policy compliance and remediate when necessary.", + "waf": "Security" + }, + { + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", + "id": "C02.09", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "services": [ + "Subscriptions" + ], + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Ensure that all subscription owners and IT core team are aware of subscription quotas and the impact they have on provision resources for a given subscription.", + "waf": "Security" + }, + { + "ammp": true, + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", + "id": "C02.10", + "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", "services": [ + "Subscriptions", "VM", + "Cost", + "AzurePolicy" + ], + "severity": "High", + "subcategory": "Subscriptions", + "text": "Use Reserved Instances where appropriate to optimize cost and ensure available capacity in target regions. Enforce the use of purchased Reserved Instance VM SKUs via Azure Policy.", + "training": "https://learn.microsoft.com/learn/paths/improve-reliability-modern-operations/", + "waf": "Security" + }, + { + "ammp": true, + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", + "id": "C02.11", + "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", + "services": [ "Monitor", - "Cost" + "Subscriptions" ], - "subcategory": "VM", - "text": "right-sizing VMs - start with monitoring usage below 5% and then work up to 40%", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "severity": "High", + "subcategory": "Subscriptions", + "text": "Enforce a dashboard, workbook, or manual process to monitor used capacity levels", + "training": "https://learn.microsoft.com/learn/paths/monitor-usage-performance-availability-resources-azure-monitor/", + "waf": "Security" }, { - "category": "Right-sizing", - "checklist": "Cost Optimization Checklist", - "guid": "2a119495-6d69-47dc-9a2e-d27b2d186f1a", - "id": "E12.05", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "ammp": true, + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "C02.12", + "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", "services": [ - "VM", + "Subscriptions", "Cost" ], - "subcategory": "VM", - "text": "containerizing an application can improve VM density and save money on scaling it", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" + "severity": "High", + "subcategory": "Subscriptions", + "text": "Enforce a process for cost management", + "training": "https://learn.microsoft.com/learn/paths/control-spending-manage-bills/", + "waf": "Security" }, { - "category": "Application Deployment", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "6d8e32a8-3892-479d-a40b-10f6b4f6f298", - "link": "https://learn.microsoft.com/azure/spring-apps/concepts-blue-green-deployment-strategies", - "services": [], + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "C02.13", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "services": [ + "Subscriptions", + "Entra" + ], "severity": "Medium", - "subcategory": "DevOps", - "text": "Azure Spring Apps permits two deployments for every app, only one of which receives production traffic. You can achieve zero downtime with blue green deployment strategies. Blue green deployment is only available in Standard and Enterprise tiers. You could automate deployment using CI/CD with ADO/GitHub actions", - "waf": "Reliability" + "subcategory": "Subscriptions", + "text": "If AD on Windows Server, establish a dedicated identity subscription in the Indentity management group, to host Windows Server Active Directory domain controllers", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { - "category": "BC and DR", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "fbcb40ac-9480-4a6d-bcf4-8081252a6716", - "link": "https://learn.microsoft.com/azure/architecture/web-apps/spring-apps/architectures/spring-apps-multi-region", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", + "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", + "id": "C02.14", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", "services": [ - "FrontDoor", - "ASR", - "TrafficManager" + "Subscriptions", + "Cost" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Azure Spring Apps instances could be created in multiple regions for your applications and traffic could be routed by Traffic Manager/Front Door.", + "subcategory": "Subscriptions", + "text": "Ensure tags are used for billing and cost management", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" + }, + { + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "250d81ce-8bbe-4f85-9051-6a18a8221e50", + "id": "C03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/regions", + "services": [ + "Cost" + ], + "severity": "High", + "subcategory": "Regions", + "text": "Select the right Azure region/s for your deployment. Azure is a global-scale cloud platform that provide global coverage through many regions and geographies. Different Azure regions have different characteristics, access and availability models, costs, capacity, and services offered, then it is important to consider all criteria and requirements", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", "waf": "Reliability" }, { - "category": "BC and DR", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "ff1ae6a7-9301-4feb-9d11-56cd72f1d4ef", - "link": "https://learn.microsoft.com/azure/reliability/reliability-spring-apps", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "19ca3f89-397d-44b1-b5b6-5e18661372ac", + "id": "C03.02", + "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-setup-guide/regions#operate-in-multiple-geographic-regions", "services": [ - "ACR" + "ASR" ], "severity": "Medium", - "subcategory": "High Availability", - "text": "In supported region, Azure Spring Apps can be deployed as zone redundant, which means that instances are automatically distributed across availability zones. This feature is only available in Standard and Enterprise tiers.", + "subcategory": "Regions", + "text": "Consider a multi-region deployment. Depending on customer size, locations, and users presence, operating in multiple regions can be a common choice to deliver services and run applications closer to them. Using a multi-region deployment is also important to provide geo disaster recovery capabilities, to eliminate the dependency from a single region capacity and diminish the risk of a temporary and localized resource capacity constraint", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", "waf": "Reliability" }, { - "category": "BC and DR", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "ffc735ad-fbb1-4802-b43f-ad6387c4c066", - "link": "https://learn.microsoft.com/azure/spring-apps/concept-understand-app-and-deployment", + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "C03.03", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", "services": [], "severity": "Medium", - "subcategory": "High Availability", - "text": "Use more than 1 app instance for your apps", + "subcategory": "Regions", + "text": "Ensure required services and features are available within the chosen deployment regions", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "7504c230-6035-4183-95a5-85762acc6075", - "link": "https://learn.microsoft.com/azure/spring-apps/diagnostic-services", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "373f482f-3e39-4d39-8aa4-7e566f6082b6", + "id": "D01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-app-delivery", "services": [ - "Monitor" + "FrontDoor", + "AppGW" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Monitor Azure Spring Apps with logs, metrics and tracing. Integrate ASA with application insights and track failures and create workbooks.", - "waf": "Reliability" + "subcategory": "App delivery", + "text": "Develop a plan for securing the delivery application content from your Workload spokes using Application Gateway and Azure Front door. You can use the Application Delivery checklist to for recommendations.", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "1eb48d58-3eec-4ef5-80b0-d2b0dde3f0c6", - "link": "https://learn.microsoft.com/azure/spring-apps/how-to-configure-enterprise-spring-cloud-gateway", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "D01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "services": [], "severity": "Medium", - "subcategory": "Scalability", - "text": "Set up autoscaling in Spring Cloud Gateway", - "waf": "Reliability" - }, - { - "category": "Operations", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "97411607-b6fd-4335-99d1-9885faf4e392", - "link": "https://learn.microsoft.com/azure/spring-apps/how-to-setup-autoscale", - "services": [], - "severity": "Low", - "subcategory": "Scalability", - "text": "Enable autoscale for the apps with Standard consumption & dedicated plan.", - "waf": "Reliability" + "subcategory": "App delivery", + "text": "Perform app delivery within landing zones for both internal-facing (corp) and external-facing apps (online).", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure Spring Apps Review", - "cost": 1, - "guid": "dfcaffd1-d27c-4ef2-998d-64c1df3a7ac3", - "link": "https://learn.microsoft.com/azure/spring-apps/overview", - "services": [], - "severity": "Medium", - "subcategory": "Support", - "text": "Use Enterprise plan for commercial support of spring boot for mission critical apps. With other tiers you get OSS support.", - "waf": "Reliability" - }, - { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "32e42e36-11c8-418b-8a0b-c510e43a18a9", - "id": "A01.01", - "services": [ - "Subscriptions", - "AVS", - "Entra" - ], - "severity": "High", - "subcategory": "Identity", - "text": "Ensure ADDS domain controller(s) are deployed in the identity subscription in native Azure", - "waf": "Security" - }, - { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", - "id": "A01.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "D01.03", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVS", - "Entra" + "DDoS" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Ensure ADDS sites and services is configured to keep authentication requests from Azure-based resources (including Azure VMware Solution) local to Azure", + "subcategory": "App delivery", + "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "de3aad1e-7c28-4ec9-9666-b7570449aa80", - "id": "A01.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "id": "D02.01", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "services": [ - "AVS", - "Entra" + "ExpressRoute" ], - "severity": "High", - "subcategory": "Identity", - "text": "Ensure that vCenter is connected to ADDS to enable authentication based on 'named user accounts'", + "severity": "Medium", + "subcategory": "Encryption", + "text": "When you're using ExpressRoute Direct, configure MACsec in order to encrypt traffic at the layer-two level between the organization's routers and MSEE. The diagram shows this encryption in flow.", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "cd289ced-6b17-4db8-8554-61e2aee3553a", - "id": "A01.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "id": "D02.02", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "services": [ - "AVS", - "Entra" + "ExpressRoute", + "VPN" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "Ensure that the connection from vCenter to ADDS is using a secure protocol (LDAPS)", + "severity": "Low", + "subcategory": "Encryption", + "text": "For scenarios where MACsec isn't an option (for example, not using ExpressRoute Direct), use a VPN gateway to establish IPsec tunnels over ExpressRoute private peering. ", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "b9d37dac-43bc-46cd-8d79-a9b24604489a", - "id": "A01.05", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", + "id": "D03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", "services": [ - "AVS", - "Entra" + "VNet" ], "severity": "Medium", - "subcategory": "Identity", - "text": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", + "subcategory": "Hub and spoke", + "text": "Consider a network design based on the traditional hub-and-spoke network topology for network scenarios that require maximum flexibility.", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "53d88e89-d17b-473b-82a5-a67e7a9ed5b3", - "id": "A01.06", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", + "id": "D03.02", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", "services": [ - "AVS", - "Entra" + "DNS", + "VNet", + "VPN", + "Entra", + "ExpressRoute", + "NVA", + "Firewall" ], "severity": "High", - "subcategory": "Identity", - "text": "Ensure that NSX-Manager is integrated with an external Identity provider", - "waf": "Security" + "subcategory": "Hub and spoke", + "text": "Ensure that shared networking services, including ExpressRoute gateways, VPN gateways, and Azure Firewall or partner NVAs in the central-hub virtual network. If necessary, also deploy DNS servers.", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "ae0e37ce-e297-411b-b352-caaab79b198d", - "id": "A01.07", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", "services": [ - "AVS", - "RBAC", - "Entra" + "NVA" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Has an RBAC model been created for use within VMware vSphere", - "waf": "Security" + "subcategory": "Hub and spoke", + "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance", + "waf": "Reliability" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "ab81932c-9fc9-4d1b-a780-36f5e6bfbb9e", - "id": "A01.08", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", + "id": "D03.04", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", "services": [ - "AVS", - "RBAC", - "Entra" + "ExpressRoute", + "ARS", + "VPN" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "RBAC permissions should be granted on ADDS groups and not on specific users", + "severity": "Low", + "subcategory": "Hub and spoke", + "text": "If you need transit between ExpressRoute and VPN gateways in hub and spoke scenarios, use Azure Route Server.", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Design Review", - "guid": "d503547c-c447-4e82-9128-a71f0f1cac6d", - "id": "A01.09", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant", + "guid": "91b9d7d5-91e1-4dcb-8f1f-fa7e465646cc", + "id": "D03.05", + "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", "services": [ - "AVS", - "RBAC", - "Entra" + "ARS", + "VNet" ], - "severity": "High", - "subcategory": "Identity", - "text": "RBAC permissions on the Azure VMware Solution resource in Azure are 'locked down' to a limited set of owners only", + "severity": "Low", + "subcategory": "Hub and spoke", + "text": "If using Route Server, use a /27 prefix for the Route Server subnet.", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "9ef1d5e8-32e4-42e3-911c-818b0a0bc510", - "id": "B01.01", - "link": "https://github.com/Azure/AzureCAT-AVS/tree/main/networking", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "id": "D03.06", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-faq#can-i-create-a-peering-connection-to-a-vnet-in-a-different-region", "services": [ - "AVS" + "VNet", + "ACR" ], - "severity": "High", - "subcategory": "Architecture", - "text": "Is the correct Azure VMware Solution connectivity model selected for the customer use case at hand", + "severity": "Medium", + "subcategory": "Hub and spoke", + "text": "For network architectures with multiple hub-and-spoke topologies across Azure regions, use global virtual network peerings between the hub VNets to connect the regions to each other. ", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-virtual-networks/", "waf": "Performance" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", - "id": "B02.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", + "id": "D03.07", + "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", "services": [ - "VPN", - "NetworkWatcher", - "Monitor", - "ExpressRoute", - "AVS" + "Monitor" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure ExpressRoute or VPN connections from on-premises to Azure are monitored using 'connection monitor'", + "severity": "Medium", + "subcategory": "Hub and spoke", + "text": "Use Azure Monitor for Networks to monitor the end-to-end state of the networks on Azure.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", - "id": "B02.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant", + "guid": "0e7c28ec-9366-4572-83b0-f4664b1d944a", + "id": "D03.08", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits", "services": [ - "VM", - "NetworkWatcher", - "Monitor", "ExpressRoute", - "AVS" + "VNet", + "Entra" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Ensure a connection monitor is created from an Azure native resource to an Azure VMware Solution virtual machine to monitor the Azure VMware Solution back-end ExpressRoute connection", - "waf": "Operations" + "subcategory": "Hub and spoke", + "text": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000)", + "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "25659d35-58fd-4772-99c9-31112d027fe4", - "id": "B02.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant", + "guid": "3d457936-e9b7-41eb-bdff-314b26450b12", + "id": "D03.09", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits", "services": [ - "VM", - "AVS", - "NetworkWatcher", - "Monitor" + "Storage" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Ensure a connection monitor is created from an on-premises resource to an Azure VMware Solution virtual machine to monitor end-2-end connectivity", - "waf": "Operations" + "subcategory": "Hub and spoke", + "text": "Consider the limit of routes per route table (400).", + "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Design Review", - "guid": "563b4dc7-4a74-48b6-933a-d1a0916a6649", - "id": "B03.01", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)", + "guid": "c76cb5a2-abe2-11ed-afa1-0242ac120002", + "id": "D03.10", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", "services": [ - "AVS", - "ARS" + "VNet" ], "severity": "High", - "subcategory": "Routing", - "text": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", - "waf": "Operations" + "subcategory": "Hub and spoke", + "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "6128a71f-0f1c-4ac6-b9ef-1d5e832e42e3", - "id": "C01.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", + "id": "D04.01", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", "services": [ - "AVS", - "Entra", - "RBAC" + "ExpressRoute" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Is Privileged Identity Management implemented for roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", - "waf": "Security" + "severity": "Medium", + "subcategory": "Hybrid", + "text": "Ensure that you have investigated the possibility to use ExpressRoute as primary connection to Azure.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "c4e2436b-b336-4d71-9f17-960eee0b9b5c", - "id": "C01.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "description": "You can use AS-path prepending and connection weights to influence traffic from Azure to on-premises, and the full range of BGP attributes in your own routers to influence traffic from on-premises to Azure.", + "guid": "f29812b2-363c-4efe-879b-599de0d5973c", + "id": "D04.02", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "services": [ - "AVS", - "Entra", - "RBAC" + "ExpressRoute" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Is Privileged Identity Management audit reporting implemented for the Azure VMware Solution PIM roles", - "waf": "Security" + "severity": "Medium", + "subcategory": "Hybrid", + "text": "When you use multiple ExpressRoute circuits, or multiple on-prem locations, make sure to optimize routing with BGP attributes, if certain paths are preferred.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "8defc4d7-21d3-41d2-90fb-707ae9eab40e", - "id": "C01.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant", + "guid": "d4cd21b0-8813-47f5-b6c4-cfd3e504547c", + "id": "D04.03", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "services": [ - "AVS", - "Entra" + "ExpressRoute", + "VPN" + ], + "severity": "Medium", + "subcategory": "Hybrid", + "text": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant", + "guid": "7025b442-f6e9-4af6-b11f-c9574916016f", + "id": "D04.04", + "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", + "services": [ + "ExpressRoute", + "Cost" ], "severity": "High", - "subcategory": "Security (identity)", - "text": "Limit use of CloudAdmin account to emergency access only", - "waf": "Security" + "subcategory": "Hybrid", + "text": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost.", + "waf": "Cost" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "d329f798-bc17-48bd-a5a0-6ca7144351d1", - "id": "C01.04", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id", + "guid": "f4e7926a-ec35-476e-a412-5dd17136bd62", + "id": "D04.05", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", "services": [ - "AVS", - "RBAC", - "Entra" + "ExpressRoute", + "Cost" ], - "severity": "Medium", - "subcategory": "Security (identity)", - "text": "Create custom RBAC roles in vCenter to implement a least-privilege model inside vCenter", - "waf": "Security" + "severity": "High", + "subcategory": "Hybrid", + "text": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU.", + "waf": "Cost" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "9dd24429-eb72-4281-97a1-51c5bb4e4f18", - "id": "C01.05", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant", + "guid": "2447ec66-138a-4720-8f1c-e16ed301d6e8", + "id": "D04.06", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", "services": [ - "AVS", - "Entra" + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Security (identity)", - "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", - "waf": "Security" + "subcategory": "Hybrid", + "text": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "586cb291-ec16-4a1d-876e-f9f141acdce5", - "id": "C01.06", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", + "id": "D04.07", + "link": "https://learn.microsoft.com/azure/networking/", "services": [ - "VM", - "AVS", - "Entra" + "ExpressRoute" ], - "severity": "High", - "subcategory": "Security (identity)", - "text": "Use a centralized identity provider to be used for workloads (VM's) running on Azure VMware Solution", - "waf": "Security" + "severity": "Medium", + "subcategory": "Hybrid", + "text": "For scenarios that require bandwidth higher than 10 Gbps or dedicated 10/100-Gbps ports, use ExpressRoute Direct.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "79377bcd-b375-41ab-8ab0-ead66e15d3d4", - "id": "C02.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", + "id": "D04.08", + "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", "services": [ - "AVS" + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Security (network)", - "text": "Is East-West traffic filtering implemented within NSX-T", - "waf": "Security" + "subcategory": "Hybrid", + "text": "When low latency is required, or throughput from on-premises to Azure must be greater than 10 Gbps, enable FastPath to bypass the ExpressRoute gateway from the data path.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "a2adb1c3-d232-46af-825c-a44e1695fddd", - "id": "C02.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant", + "guid": "4d873974-8b66-42d6-b15f-512a65498f6d", + "id": "D04.09", + "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", "services": [ - "Firewall", - "AVS", - "AppGW" + "VPN" ], - "severity": "High", - "subcategory": "Security (network)", - "text": "Workloads on Azure VMware Solution are not directly exposed to the internet. Traffic is filtered and inspected by Azure Application Gateway, Azure Firewall or 3rd party solutions", - "waf": "Security" + "severity": "Medium", + "subcategory": "Hybrid", + "text": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available).", + "training": "https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "eace4cb1-deb4-4c65-8c3f-c14eeab36938", - "id": "C02.03", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "id": "D04.10", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "services": [ - "AVS" + "ExpressRoute", + "Cost" ], "severity": "High", - "subcategory": "Security (network)", - "text": "Auditing and logging is implemented for inbound internet requests to Azure VMware Solution and Azure VMware Solution based workloads", - "waf": "Security" + "subcategory": "Hybrid", + "text": "If using ExpressRoute Direct, consider using ExpressRoute Local circuits to the local Azure regions to save costs", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Cost" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "29e3eec2-1836-487a-8077-a2b5945bda43", - "id": "C02.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "id": "D04.11", + "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", "services": [ - "AVS", - "Monitor" + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Security (network)", - "text": "Session monitoring is implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", + "subcategory": "Hybrid", + "text": "When traffic isolation or dedicated bandwidth is required, such as for separating production and nonproduction environments, use different ExpressRoute circuits. It will help you ensure isolated routing domains and alleviate noisy-neighbor risks.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "334fdf91-c234-4182-a652-75269440b4be", - "id": "C02.05", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "b30e38c3-f298-412b-8363-cefe179b599d", + "id": "D04.12", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", "services": [ - "VPN", - "VNet", "ExpressRoute", - "AVS", - "DDoS" + "Monitor" ], "severity": "Medium", - "subcategory": "Security (network)", - "text": "Is DDoS standard protection enabled on ExR/VPN Gateway subnet in Azure", - "waf": "Security" + "subcategory": "Hybrid", + "text": "Monitor ExpressRoute availability and utilization using built-in Express Route Insights.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "3d3e0843-276d-44bd-a015-bcf219e4a1eb", - "id": "C02.06", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", + "id": "D04.13", + "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", "services": [ - "AVS" + "Monitor", + "ACR", + "NetworkWatcher" ], "severity": "Medium", - "subcategory": "Security (network)", - "text": "Use a dedicated privileged access workstation (PAW) to manage Azure VMware Solution, vCenter, NSX manager and HCX manager", - "waf": "Security" + "subcategory": "Hybrid", + "text": "Use Connection Monitor for connectivity monitoring across the environment.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "9ccbd869-266a-4cca-874f-aa19bf39d95d", - "id": "C03.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", + "id": "D04.14", + "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", "services": [ - "AVS", - "Defender" + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Security (guest/VM)", - "text": "Enable Advanced Threat Detection (Microsoft Defender for Cloud aka ASC) for workloads running on Azure VMware Solution", - "waf": "Security" + "subcategory": "Hybrid", + "text": "Use ExpressRoute circuits from different peering locations for redundancy.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "44c7c891-9ca1-4f6d-9315-ae524ba34d45", - "id": "C03.02", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "id": "D04.15", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", "services": [ - "AVS", - "Arc" + "VM" ], - "severity": "Medium", - "subcategory": "Security (guest/VM)", - "text": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", - "waf": "Security" + "severity": "High", + "subcategory": "Hybrid", + "text": "If you are deploying at least two VMs running AD DS as domain controllers, add them to different Availability Zones. If not available in the region, deploy in an Availability Set.", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "85e12139-bd7b-4b01-8f7b-95ef6e043e2a", - "id": "C03.03", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "558fd772-49b8-4211-82df-27ee412e7f98", + "id": "D05.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "SQL", - "AVS" + "VNet", + "ACR" ], - "severity": "Low", - "subcategory": "Security (guest/VM)", - "text": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", + "severity": "High", + "subcategory": "IP plan", + "text": "Ensure no overlapping IP address spaces across Azure regions and on-premises locations are used", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "a3592718-e6e2-4051-9267-6ae46691e883", - "id": "C03.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr", + "guid": "3f630472-2dd6-49c5-a5c2-622f54b69bad", + "id": "D05.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "AVS", - "AKV" + "VNet" ], "severity": "Low", - "subcategory": "Security (guest/VM)", - "text": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", + "subcategory": "IP plan", + "text": "Use IP addresses from the address allocation ranges for private internets (RFC 1918).", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "5ac94222-3e13-4810-9230-81a941741583", - "id": "C03.05", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant", + "guid": "33aad5e8-c68e-41d7-9667-313b4f5664b5", + "id": "D05.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "AVS" + "VNet" ], "severity": "High", - "subcategory": "Security (guest/VM)", - "text": "Ensure extended security update support is configured for workloads running on Azure VMware Solution (Azure VMware Solution is eligible for ESU)", - "waf": "Security" + "subcategory": "IP plan", + "text": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16) ", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "3ef7ad7c-6d37-4331-95c7-acbe44bbe609", - "id": "C04.01", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", + "id": "D05.04", + "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", "services": [ - "VM", - "AVS", - "Storage", - "AzurePolicy" + "VNet" ], "severity": "High", - "subcategory": "Governance (platform)", - "text": "Ensure that the appropriate VM template storage policy is used", - "waf": "Performance" + "subcategory": "IP plan", + "text": "Avoid using overlapping IP address ranges for production and DR sites.", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "waf": "Reliability" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "d89f2e87-7784-424d-9167-85c6fa95b96a", - "id": "C04.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", + "id": "D05.05", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "services": [ - "AVS", - "ASR" + "DNS", + "VNet" ], - "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "IP plan", + "text": "For environments where name resolution in Azure is all that's required, use Azure Private DNS for resolution with a delegated zone for name resolution (such as 'azure.contoso.com').", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "d88408f3-7273-44c8-96ba-280214590146", - "id": "C04.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", + "id": "D05.06", + "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", "services": [ - "AVS", - "Storage", - "AzurePolicy" + "DNS", + "VNet", + "ACR" ], - "severity": "High", - "subcategory": "Governance (platform)", - "text": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "IP plan", + "text": "For environments where name resolution across Azure and on-premises is required, consider using Azure DNS Private Resolver.", + "training": "https://learn.microsoft.com/training/modules/intro-to-azure-dns-private-resolver/", + "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "5d38e53f-9ccb-4d86-a266-acca274faa19", - "id": "C04.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", + "id": "D05.07", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "services": [ - "AVS" + "DNS", + "VNet" ], - "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", + "severity": "Low", + "subcategory": "IP plan", + "text": "Special workloads that require and deploy their own DNS (such as Red Hat OpenShift) should use their preferred DNS solution.", "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "bf39d95d-44c7-4c89-89ca-1f6d5315ae52", - "id": "C04.05", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "614658d3-558f-4d77-849b-821112df27ee", + "id": "D05.08", + "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", "services": [ - "AVS", - "AzurePolicy" + "VM", + "VNet", + "DNS" ], - "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Ensure that you have a policy around ESXi host density and efficiency, keeping in mind the lead time for requesting new nodes", + "severity": "High", + "subcategory": "IP plan", + "text": "Enable auto-registration for Azure DNS to automatically manage the lifecycle of the DNS records for the virtual machines deployed within a virtual network.", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "4ba34d45-85e1-4213-abd7-bb012f7b95ef", - "id": "C04.06", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "id": "D06.01", + "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", "services": [ - "AVS", - "Cost" + "Bastion" ], "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Ensure a good cost management process is in place for Azure VMware Solution - Azure Cost Management can be used", - "waf": "Cost" - }, - { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "6e043e2a-a359-4271-ae6e-205172676ae4", - "id": "C04.07", - "services": [ - "AVS", - "Cost" - ], - "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Are Azure reserved instances used to optimize cost for using Azure VMware Solution", - "waf": "Cost" + "subcategory": "Internet", + "text": "Consider using Azure Bastion to securely connect to your network.", + "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "6691e883-5ac9-4422-83e1-3810523081a9", - "id": "C04.08", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant", + "guid": "6eab9eb6-762b-485e-8ea8-15aa5dba0bd0", + "id": "D06.02", + "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet", "services": [ - "AVS" + "VNet", + "Bastion" ], "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Consider the use of Azure Private-Link when using other Azure Native Services", + "subcategory": "Internet", + "text": "Use Azure Bastion in a subnet /26 or larger.", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "48b262d6-cc5f-4512-a253-98e6db9d37da", - "id": "C05.01", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", + "id": "D06.03", + "link": "https://learn.microsoft.com/azure/app-service/networking-features", "services": [ - "VM", - "AVS", - "Defender" + "Firewall" ], - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Enable Microsoft Defender for Cloud for Azure VMware Solution guest VM workloads", + "severity": "High", + "subcategory": "Internet", + "text": "Use Azure Firewall to govern Azure outbound traffic to the internet, non-HTTP/S inbound connections, and East/West traffic filtering (if the organization requires it)", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "41741583-3ef7-4ad7-a6d3-733165c7acbe", - "id": "C05.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", + "id": "D06.04", + "link": "https://learn.microsoft.com/azure/firewall/", "services": [ - "VM", - "AVS", - "Arc" + "Firewall", + "RBAC", + "ACR", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Use Azure Arc enabled servers to manage your Azure VMware Solution guest VM workloads", + "subcategory": "Internet", + "text": "Create a global Azure Firewall policy to govern security posture across the global network environment and assign it to all Azure Firewall instances. Allow for granular policies to meet requirements of specific regions by delegating incremental firewall policies to local security teams via Azure role-based access control.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "88f03a4d-2cd4-463c-abbc-868295abc91a", - "id": "C05.03", - "services": [ - "AVS" - ], - "severity": "High", - "subcategory": "Governance (guest/VM)", - "text": "Enable Diagnostic and metric logging on Azure VMware Solution", - "waf": "Operations" - }, - { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "4ed90dae-2cc8-44c4-9b6b-781cbafe6c46", - "id": "C05.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", + "id": "D06.05", + "link": "https://learn.microsoft.com/azure/firewall/", "services": [ - "VM", - "AVS", - "Monitor" + "Firewall" ], - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Deploy the Log Analytics Agents to Azure VMware Solution guest VM workloads", - "waf": "Operations" + "severity": "Low", + "subcategory": "Internet", + "text": "Configure supported partner SaaS security providers within Firewall Manager if the organization wants to use such solutions to help protect outbound connections.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "589d457a-927c-4397-9d11-02cad6aae11e", - "id": "C05.05", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", + "id": "D06.06", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "services": [ - "VM", - "Backup", - "AVS", + "WAF", + "ACR", + "FrontDoor", "AzurePolicy" ], "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", - "waf": "Operations" + "subcategory": "Internet", + "text": "Use Azure Front Door and WAF policies to provide global protection across Azure regions for inbound HTTP/S connections to a landing zone.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "ee29711b-d352-4caa-ab79-b198dab81932", - "id": "C06.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", + "id": "D06.07", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVS", - "Defender", - "Monitor" + "AzurePolicy", + "WAF", + "FrontDoor", + "AppGW" ], - "severity": "Medium", - "subcategory": "Compliance", - "text": "Use Microsoft Defender for Cloud for compliance monitoring of workloads running on Azure VMware Solution", + "severity": "Low", + "subcategory": "Internet", + "text": "When using Azure Front Door and Azure Application Gateway to help protect HTTP/S apps, use WAF policies in Azure Front Door. Lock down Azure Application Gateway to receive traffic only from Azure Front Door.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "c9fc9d1b-b780-436f-9e6b-fbb9ed503547", - "id": "C06.02", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", + "id": "D06.08", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "AVS", - "Defender" + "VNet", + "WAF" ], - "severity": "Medium", - "subcategory": "Compliance", - "text": "Are the applicable compliance baselines added to Microsoft Defender for Cloud", + "severity": "High", + "subcategory": "Internet", + "text": "Deploy WAFs and other reverse proxies are required for inbound HTTP/S connections, deploy them within a landing-zone virtual network and together with the apps that they're protecting and exposing to the internet.", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "cc447e82-6128-4a71-b0f1-cac6d9ef1d5e", - "id": "C06.03", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", + "id": "D06.09", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", "services": [ - "AVS" + "VNet", + "DDoS" ], "severity": "High", - "subcategory": "Compliance", - "text": "Was data residency evaluated when selecting Azure regions to use for Azure VMware Solution deployment", + "subcategory": "Internet", + "text": "Use Azure DDoS Network or IP Protection plans to help protect Public IP Addresses endpoints within the virtual networks.", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Security" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Design Review", - "guid": "832e42e3-611c-4818-a0a0-bc510e43a18a", - "id": "C06.04", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", + "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "id": "D06.10", + "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", "services": [ - "AVS" + "Firewall", + "DNS" ], "severity": "High", - "subcategory": "Compliance", - "text": "Are data processing implications (service provider / service consumer model) clear and documented", + "subcategory": "Internet", + "text": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules.", "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "e43a18a9-cd28-49ce-b6b1-7db8255461e2", - "id": "D01.01", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", + "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "id": "D06.11", + "link": "https://learn.microsoft.com/azure/firewall/premium-features", "services": [ - "AVS", - "Monitor" + "Firewall" ], "severity": "High", - "subcategory": "Monitoring", - "text": "Create dashboards to enable core Azure VMware Solution monitoring insights", - "waf": "Operations" + "subcategory": "Internet", + "text": "Use Azure Firewall Premium for additional security and protection.", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "6b84ee5d-f47d-42d9-8881-b1cd5d1e54a2", - "id": "D01.02", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", + "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "id": "D06.12", + "link": "https://learn.microsoft.com/azure/firewall/premium-features", "services": [ - "AVS", - "Monitor" + "Firewall" ], "severity": "High", - "subcategory": "Monitoring", - "text": "Create warning alerts for critical thresholds for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", - "waf": "Operations" + "subcategory": "Internet", + "text": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection.", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "9659e396-80e7-4828-ac93-5657d02bff45", - "id": "D01.03", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", + "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "id": "D06.13", + "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", "services": [ - "AVS", - "Monitor" + "Firewall" ], "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure critical alert is created to monitor if vSAN consumption is below 75% as this is a support threshold from VMware", - "waf": "Operations" + "subcategory": "Internet", + "text": "Configure Azure Firewall IDPS mode to Deny for additional protection.", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "64b0d934-a348-4726-be79-d6b5c3a36495", - "id": "D01.04", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant", + "guid": "a3784907-9836-4271-aafc-93535f8ec08b", + "id": "D06.14", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "services": [ - "AVS", - "Monitor" + "VWAN", + "VNet", + "Storage", + "NVA", + "Firewall" ], "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure alerts are configured for Azure Service Health alerts and notifications", - "waf": "Operations" + "subcategory": "Internet", + "text": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "b6abad38-aad5-43cc-99e1-d86667357c54", - "id": "D01.05", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "b034c01e-110b-463a-b36e-e3346e57f225", + "id": "D06.15", + "link": "https://learn.microsoft.com/en-us/azure/virtual-network/ip-services/default-outbound-access", + "services": [], + "severity": "High", + "subcategory": "Internet", + "text": "Assess and review network outbound traffic configuration and strategy before the upcoming breaking change. On September 30, 2025, default outbound access for new deployments will be retired and only explicit access configurations will be allowed", + "waf": "Reliability" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "D07.01", + "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "services": [ - "AVS", - "Storage", - "Monitor" + "VNet" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Configure Azure VMware Solution logging to be send to an Azure Storage account or Azure EventHub for processing", - "waf": "Operations" + "severity": "High", + "subcategory": "PaaS", + "text": "Ensure that control-plane communication for Azure PaaS services injected into a virtual network is not broken, for example with a 0.0.0.0/0 route or an NSG rule that blocks control plane traffic.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "9674c5ed-85b8-459c-9733-be2b1a27b775", - "id": "D01.06", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", + "id": "D07.02", + "link": "https://learn.microsoft.com/azure/app-service/networking-features", "services": [ - "AVS", - "Monitor" + "PrivateLink" ], - "severity": "Low", - "subcategory": "Monitoring", - "text": "If deep insight in VMware vSphere is required: Is vRealize Operations and/or vRealize Network Insights used in the solution?", - "waf": "Operations" + "severity": "Medium", + "subcategory": "PaaS", + "text": "Use Private Link, where available, for shared Azure PaaS services.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "a91be1f3-88f0-43a4-b2cd-463cbbbc8682", - "id": "D02.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", + "id": "D07.03", + "link": "https://learn.microsoft.com/azure/app-service/networking-features", "services": [ - "VM", - "AVS", - "Storage", - "AzurePolicy" + "ExpressRoute", + "PrivateLink" ], - "severity": "High", - "subcategory": "Operations", - "text": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning", - "waf": "Operations" + "severity": "Medium", + "subcategory": "PaaS", + "text": "Access Azure PaaS services from on-premises via private endpoints and ExpressRoute private peering. This method avoids transiting over the public internet.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "d9ef1d5e-832d-442e-9611-c818b0afbc51", - "id": "D02.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc", + "guid": "4704489a-8042-4d88-b79d-17b73b22a5a6", + "id": "D07.04", + "link": "https://learn.microsoft.com/azure/app-service/networking-features", "services": [ - "AVS" + "VNet" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure vSphere content libraries are not placed on vSAN as vSAN is a finite resource", - "waf": "Operations" + "subcategory": "PaaS", + "text": "Don't enable virtual network service endpoints by default on all subnets.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "0e43a18a-9cd2-489b-bd6b-17db8255461e", - "id": "D02.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", + "id": "D07.05", + "link": "https://learn.microsoft.com/azure/app-service/networking-features", "services": [ - "Backup", - "AVS", - "Storage" + "Firewall", + "DNS", + "NVA", + "PrivateLink" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", - "waf": "Operations" + "subcategory": "PaaS", + "text": "Filter egress traffic to Azure PaaS services using FQDNs instead of IP addresses in Azure Firewall or an NVA to prevent data exfiltration. If using Private Link you can block all FQDNs, otherwise allow only the required PaaS services.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "2aee3453-aec8-4339-848b-262d6cc5f512", - "id": "D02.04", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant", + "guid": "22d6419e-b627-4d95-9e7d-019fa759387f", + "id": "D08.01", + "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", "services": [ - "AVS", - "Arc" + "Firewall", + "VNet" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure workloads running on Azure VMware Solution are hybrid managed using Azure Arc for Servers (Arc for Azure VMware Solution is in preview)", - "waf": "Operations" + "severity": "High", + "subcategory": "Segmentation", + "text": "Use a /26 prefix for your Azure Firewall subnets.", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "925398e6-da9d-437d-ac43-bc6cd1d79a9b", - "id": "D02.05", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant", + "guid": "f2aad7e3-bb03-4adc-8606-4123d342a917", + "id": "D08.02", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", "services": [ - "AVS", - "Monitor" + "ExpressRoute", + "VPN", + "VNet" ], - "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", - "waf": "Operations" + "severity": "High", + "subcategory": "Segmentation", + "text": "Use at least a /27 prefix for your Gateway subnets", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "24604489-a8f4-42d7-ae78-cb6a33bd2a09", - "id": "D02.06", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)", + "guid": "11deb39d-8299-4e47-bbe0-0fb5a36318a8", + "id": "D08.03", + "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", "services": [ - "AVS" + "VNet" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Include workloads running on Azure VMware Solution in existing update management tooling or in Azure Update Management", - "waf": "Operations" + "subcategory": "Segmentation", + "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity.", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "17e7a8d9-0ae0-4e27-aee2-9711bd352caa", - "id": "D02.07", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", + "id": "D08.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", "services": [ - "AVS", - "AzurePolicy", - "Monitor" + "VNet" ], "severity": "Medium", - "subcategory": "Operations", - "text": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", - "waf": "Operations" + "subcategory": "Segmentation", + "text": "Delegate subnet creation to the landing zone owner. ", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "ab79b188-dab8-4193-8c9f-c9d1bb77036f", - "id": "D02.08", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", + "id": "D08.05", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "VM", - "AVS", - "Storage" + "VNet", + "ACR" ], - "severity": "High", - "subcategory": "Operations", - "text": "When ANF is used to extend storage for Azure VMware Solution, ensure it is used at the VM level only for now (ANF as NFS datastore is still in private preview)", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Segmentation", + "text": "Use NSGs to help protect traffic across subnets, as well as east/west traffic across the platform (traffic between landing zones).", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "waf": "Security" }, { - "category": "Management", - "checklist": "Azure VMware Solution Design Review", - "guid": "aee3553a-fc83-4392-98b2-62d6cc5f5129", - "id": "D03.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)", + "guid": "9c2299c4-d7b5-47d0-a655-562f2b3e4563", + "id": "D08.06", "services": [ - "AVS", - "Defender" + "VM", + "VNet" ], "severity": "Medium", - "subcategory": "Security", - "text": "Ensure workloads running on Azure VMware Solution are onboarded to Microsoft Defender for Cloud", + "subcategory": "Segmentation", + "text": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", "waf": "Security" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "25398e6d-b9d3-47da-a43b-c6cd1d79a9b2", - "id": "E01.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", + "id": "D08.07", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "services": [ - "Backup", - "AVS" + "NVA", + "VNet", + "Entra" ], "severity": "Medium", - "subcategory": "Backup", - "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", - "waf": "Reliability" + "subcategory": "Segmentation", + "text": "Use NSGs and application security groups to micro-segment traffic within the landing zone and avoid using a central NVA to filter traffic flows.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "waf": "Security" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "5e6bfbb9-ed50-4354-9cc4-47e826028a71", - "id": "E02.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "dfe237de-143b-416c-91d7-aa9b64704489", + "id": "D08.08", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "services": [ - "AVS", - "ASR" + "VNet", + "NetworkWatcher" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", - "waf": "Reliability" + "subcategory": "Segmentation", + "text": "Enable NSG flow logs and feed them into Traffic Analytics to gain insights into internal and external traffic flows.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", + "waf": "Security" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "f0f1cac6-d9ef-41d5-b832-d42e3611c818", - "id": "E02.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", + "id": "D09.01", + "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", "services": [ - "AVS", - "ASR" + "VWAN" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", - "waf": "Reliability" + "subcategory": "Virtual WAN", + "text": "Consider Virtual WAN for simplified Azure networking management, and make sure your scenario is explicitly described in the list of Virtual WAN routing designs", + "training": "https://learn.microsoft.com/learn/modules/introduction-azure-virtual-wan/", + "waf": "Operations" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "b0afbc51-0e43-4a18-a9cd-289bed6b17db", - "id": "E02.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", + "id": "D09.02", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "services": [ - "AVS", - "ASR" + "VWAN", + "ACR" ], - "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Use Automated recovery plans with either of the Disaster solutions, avoid manual tasks as much as possible", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Virtual WAN", + "text": "Use a Virtual WAN hub per Azure region to connect multiple landing zones together across Azure regions via a common global Azure Virtual WAN.", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "8255461e-2aee-4345-9aec-8339248b262d", - "id": "E02.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", + "id": "D09.03", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "services": [ - "AVS", - "ASR" + "VWAN", + "ACR" ], - "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use the geopolitical region pair as the secondary disaster recovery environment", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Virtual WAN", + "text": "Follow the principle 'traffic in Azure stays in Azure' so that communication across resources in Azure occurs via the Microsoft backbone network", + "waf": "Performance" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "6cc5f512-9253-498e-9da9-d37dac43bc6c", - "id": "E02.05", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", + "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", + "id": "D09.04", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "services": [ - "AVS", - "ASR" + "Firewall", + "VWAN" ], - "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Virtual WAN", + "text": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "d1d79a9b-2460-4448-aa8f-42d78e78cb6a", - "id": "E02.06", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "id": "D09.05", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "services": [ - "NVA", - "AVS", - "ExpressRoute", - "ASR" + "VWAN" ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Will ExpressRoute Global Reach be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or is routing done through network virtual appliances?", + "subcategory": "Virtual WAN", + "text": "Ensure that the network architecture is within the Azure Virtual WAN limits.", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "33bd2a09-17e7-4a8d-a0ae-0e27cee29711", - "id": "E03.01", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "id": "D09.06", + "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", "services": [ - "Backup", - "AVS" + "VWAN", + "Monitor" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Use MABS as your backup solution", - "waf": "Reliability" + "subcategory": "Virtual WAN", + "text": "Use Azure Monitor Insights for Virtual WAN to monitor the end-to-end topology of the Virtual WAN, status, and key metrics.", + "waf": "Operations" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "bd352caa-ab79-4b18-adab-81932c9fc9d1", - "id": "E03.02", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "id": "D09.07", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", "services": [ - "Backup", - "AVS" + "VWAN" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", + "subcategory": "Virtual WAN", + "text": "Make sure that your IaC deployments does not disable branch-to-branch traffic in Virtual WAN, unless these flows should be explicitly blocked.", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "bb77036f-5e6b-4fbb-aed5-03547cc447e8", - "id": "E03.03", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "id": "D09.08", + "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", "services": [ - "AVS" + "ExpressRoute", + "VWAN", + "VPN" ], "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", + "subcategory": "Virtual WAN", + "text": "Use AS-Path as hub routing preference, since it is more flexible than ExpressRoute or VPN.", "waf": "Reliability" }, { - "category": "BCDR", - "checklist": "Azure VMware Solution Design Review", - "guid": "26028a71-f0f1-4cac-9d9e-f1d5e832d42e", - "id": "E03.04", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "id": "D09.09", + "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", "services": [ - "AVS" + "VWAN" ], - "severity": "Low", - "subcategory": "Business Continuity", - "text": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", + "severity": "Medium", + "subcategory": "Virtual WAN", + "text": "Make sure that your IaC deployments are configuring label-based propagation in Virtual WAN, otherwise connectivity between virtual hubs will be impaired.", "waf": "Reliability" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "4604489a-8f42-4d78-b78c-b7a33bd2a0a1", - "id": "F01.01", + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "9c75dfef-573c-461c-a698-68598595581a", + "id": "D09.10", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", "services": [ - "AVS" + "VWAN" ], - "severity": "Low", - "subcategory": "Deployment strategy", - "text": "For manual deployments, all configuration and deployments must be documented", - "waf": "Operations" + "severity": "High", + "subcategory": "Virtual WAN", + "text": "Assign enough IP space to virtual hubs, ideally a /23 prefix.", + "waf": "Reliability" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "7e7a8d90-ae0e-437c-be29-711bd352caaa", - "id": "F01.02", + "ammp": true, + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", + "id": "E01.01", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS" + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Deployment strategy", - "text": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", - "waf": "Operations" + "severity": "High", + "subcategory": "Governance", + "text": "Leverage Azure Policy strategically, define controls for your environment, using Policy Initiatives to group related policies.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "b79b198d-ab81-4932-a9fc-9d1bb78036f5", - "id": "F02.01", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", + "id": "E01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", "services": [ - "AVS" + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployments, deploy a minimal private cloud and scale as needed", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Governance", + "text": "Identify required Azure tags and use the 'append' policy mode to enforce usage via Azure Policy.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "e6bfbb9e-d503-4547-ac44-7e826128a71f", - "id": "F02.02", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", + "id": "E01.03", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS" + "RBAC", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployments, request or reserve quota prior to starting the deployment", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Governance", + "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "0f1cac6d-9ef1-4d5e-a32e-42e3611c818b", - "id": "F02.03", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "223ace8c-b123-408c-a501-7f154e3ab369", + "id": "E01.04", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS", + "Subscriptions", "AzurePolicy" ], - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployment, ensure that relevant resource locks are created through the automation or through Azure Policy for proper governance", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Governance", + "text": "Establish Azure Policy definitions at the intermediate root management group so that they can be assigned at inherited scopes", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "e2cc95d4-8c6b-4791-bca0-f6c56589e558", - "id": "F03.01", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "3829e7e3-1618-4368-9a04-77a209945bda", + "id": "E01.05", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS", - "AKV" + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Governance", + "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "255461e2-aee3-4553-afc8-339248b262d6", - "id": "F03.02", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "43334f24-9116-4341-a2ba-527526944008", + "id": "E01.06", + "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "services": [ - "AVS", - "ExpressRoute", - "AKV" + "Subscriptions", + "AzurePolicy" ], "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", - "waf": "Operations" + "subcategory": "Governance", + "text": "Use Azure Policy to control which services users can provision at the subscription/management group level", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "cc5f5129-2539-48e6-bb9d-37dac43bc6cd", - "id": "F03.03", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", + "id": "E01.07", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AVS" + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Define resource dependencies for serializing actions in IaC when many resources need to be deployed in/on Azure VMware Solution as Azure VMware Solution only supports a limited number of parallel operations.", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Governance", + "text": "Use built-in policies where possible to minimize operational overhead.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "1d79a9b2-4604-4489-a8f4-2d78e78cb7a3", - "id": "F03.04", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "description": "Assigning the Resource Policy Contributor role to specific scopes allows you to delegate policy management to relevant teams. For instance, a central IT team may oversee management group-level policies, while application teams handle policies for their subscriptions, enabling distributed governance with adherence to organizational standards.", + "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", + "id": "E01.08", + "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "services": [ - "AVS" + "Subscriptions", + "RBAC", + "Entra", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Governance", + "text": "Assign the built-in Resource Policy Contributor role at a particular scope to enable application-level governance.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "3bd2a0a1-7e7a-48d9-8ae0-e37cee29711b", - "id": "F04.01", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "19048384-5c98-46cb-8913-156a12476e49", + "id": "E01.09", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ "Subscriptions", - "AVS" + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", - "waf": "Performance" + "subcategory": "Governance", + "text": "Limit the number of Azure Policy assignments made at the root management group scope to avoid managing through exclusions at inherited scopes.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "d352caaa-b79b-4198-bab8-1932c9fc9d1b", - "id": "F04.02", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", + "id": "E01.10", + "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "services": [ - "AVS", - "Storage", "AzurePolicy" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", - "waf": "Performance" + "subcategory": "Governance", + "text": "If any data sovereignty requirements exist, Azure Policies can be deployed to enforce them", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "b78036f5-e6bf-4bb9-bd50-3547cc447e82", - "id": "F04.03", + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", + "id": "E02.01", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "services": [ - "AVS" + "TrafficManager", + "VM", + "Cost" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", - "waf": "Performance" + "severity": "Low", + "subcategory": "Optimize your cloud investment", + "text": "Consider using automation tags to start/stop VM's in your environment to save on cost.", + "waf": "Security" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "bf15bce2-19e4-4a0e-a588-79424d226786", - "id": "F04.04", + "category": "Management ", + "checklist": "Azure Landing Zone Review", + "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", + "id": "E02.01", + "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "services": [ - "AVS" + "VM" ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", - "waf": "Performance" + "subcategory": "Scalability", + "text": "Leverage Azure Virtual Machine Scale sets to scale in and out based on the load.", + "waf": "Reliability" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "d20b56c5-7be5-4851-a0f8-3835c586cb29", - "id": "F04.05", - "services": [ - "AVS" - ], + "category": "Governance", + "checklist": "Azure Landing Zone Review", + "guid": "29fd366b-a180-452b-9bd7-954b7700c667", + "id": "E02.02", + "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json", + "services": [ + "Monitor", + "TrafficManager", + "Cost" + ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Define and enforce scale in/out maximum limits for your environment in the automations", - "waf": "Performance" + "subcategory": "Optimize your cloud investment", + "text": "Configure 'Actual' and 'Forecasted' Budget Alerts.", + "waf": "Cost" }, { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Design Review", - "guid": "1dc15a1c-075e-4e9f-841a-cccd579376bc", - "id": "F04.06", + "ammp": true, + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", + "id": "F01.01", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "services": [ - "AVS", - "Monitor" + "WAF", + "FrontDoor", + "AppGW" ], - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", + "severity": "High", + "subcategory": "App delivery", + "text": "Add diagnostic settings to save WAF logs from application delivery services like Azure Front Door and Azure Application Gateway. Regularly review the logs to check for attacks and for false positive detections.", "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "06862505-2d9a-4874-9491-2837b00a3475", - "link": "https://learn.microsoft.com/azure/api-management/backends", + "checklist": "Azure Landing Zone Review", + "guid": "7f408960-c626-44cb-a018-347c8d790cdf", + "id": "F01.02", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "services": [ - "APIM" + "Sentinel", + "WAF", + "FrontDoor", + "AppGW" ], "severity": "Medium", - "subcategory": "Best practices", - "text": "Use Backends feature to eliminate redundant API backend configurations" + "subcategory": "App delivery", + "text": "Send WAF logs from your application delivery services like Azure Front Door and Azure Application Gateway to Microsoft Sentinel. Detect attacks and integrate WAF telemetry into your overall Azure environment.", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "03b125d5-b69b-4739-b7fd-84b86da4933e", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-properties?tabs=azure-portal", - "services": [ - "AzurePolicy", - "APIM" - ], + "checklist": "Azure Landing Zone Review", + "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", + "id": "F02.01", + "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", + "services": [], "severity": "Medium", - "subcategory": "Best practices", - "text": "Use Named Values to store common values that can be used in policies" + "subcategory": "Data Protection", + "text": "Consider cross-region replication in Azure for BCDR with paired regions", + "waf": "Reliability" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "beae759e-4ddb-4326-bf26-47f87d3454b6", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-deploy-multi-region", + "checklist": "Azure Landing Zone Review", + "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", + "id": "F02.02", + "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "services": [ - "ASR", - "APIM" + "Backup" ], "severity": "Medium", - "subcategory": "Business continuity and disaster recovery", - "text": "Deploy to multiple Azure regions" + "subcategory": "Data Protection", + "text": "When using Azure Backup, consider the different backup types (GRS, ZRS & LRS) as the default setting is GRS", + "waf": "Reliability" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "9c8d1664-dd9a-49d4-bd83-950af0af4044", - "link": "https://learn.microsoft.com/azure/api-management/high-availability", + "checklist": "Azure Landing Zone Review", + "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", + "id": "F03.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "ASR", - "APIM" + "Monitor", + "RBAC", + "Entra", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Business continuity and disaster recovery", - "text": "Deploy at least two scale units spread over two availability zones per region for best availability and performance" + "subcategory": "Monitoring", + "text": "Use a single monitor logs workspace to manage platforms centrally except where Azure role-based access control (Azure RBAC), data sovereignty requirements, or data retention policies mandate separate workspaces.", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "8d2db6e8-85c6-4118-a52c-ae76a4f27934", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#service-native-backup-capability", + "checklist": "Azure Landing Zone Review", + "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "F03.02", "services": [ - "Backup", - "ASR", - "APIM" + "Monitor" ], - "severity": "High", - "subcategory": "Business continuity and disaster recovery", - "text": "Ensure there is an automated backup routine" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Is the landing zone documented?", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "f96ddac5-77ec-4fa9-8833-4327f052059e", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-cache-external", + "checklist": "Azure Landing Zone Review", + "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", + "id": "F03.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "services": [ - "AzurePolicy", - "APIM" + "ARS", + "Monitor" ], "severity": "Medium", - "subcategory": "Performance and scalability", - "text": "Consider using a external cache policy for APIs that can benefit from caching", - "training": "https://learn.microsoft.com/training/modules/improve-api-performance-with-apim-caching-policy/" + "subcategory": "Monitoring", + "text": "Use Azure Monitor Logs when log retention requirements exceed two years. You can currently keep data in archived state for up to 7 years.", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "8210699f-8d43-45c2-8f19-57e54134bd8f", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-log-event-hubs", + "checklist": "Azure Landing Zone Review", + "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", + "id": "F03.04", + "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/govern/policy-compliance/regulatory-compliance", "services": [ - "EventHubs", - "AzurePolicy", - "APIM" + "Monitor", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Performance and scalability", - "text": "If you need to log at high performance levels, consider Event Hubs policy" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Policy for access control and compliance reporting. Azure Policy provides the ability to enforce organization-wide settings to ensure consistent policy adherence and fast violation detection. ", + "training": "https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effects", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "121bfc39-fa7b-4096-b93b-ab56c1bc0bed", - "link": "https://learn.microsoft.com/azure/api-management/api-management-sample-flexible-throttling", + "checklist": "Azure Landing Zone Review", + "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", + "id": "F03.05", + "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "services": [ - "AzurePolicy", - "APIM" + "Monitor", + "VM", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Performance and scalability", - "text": "Apply throttling policies to control the number of requests per second", - "training": "https://learn.microsoft.com/training/modules/protect-apis-on-api-management/" + "subcategory": "Monitoring", + "text": "Monitor in-guest virtual machine (VM) configuration drift using Azure Policy. Enabling guest configuration audit capabilities through policy helps application team workloads to immediately consume feature capabilities with little effort.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "bb5f356b-3daf-47a2-a9ee-867a8100bbd5", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-autoscale", + "checklist": "Azure Landing Zone Review", + "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", + "id": "F03.06", + "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "services": [ - "APIM" + "Monitor", + "VM" ], "severity": "Medium", - "subcategory": "Performance and scalability", - "text": "Configure autoscaling to scale out the number of instances when the load increases" + "subcategory": "Monitoring", + "text": "Use Update Management in Azure Automation as a long-term patching mechanism for both Windows and Linux VMs. ", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "Operations" }, { "category": "Management", - "checklist": "Azure API Management Review", - "guid": "84b94abb-59b6-4b9d-8587-3413669468e8", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-provision-self-hosted-gateway", + "checklist": "Azure Landing Zone Review", + "guid": "90483845-c986-4cb2-a131-56a12476e49f", + "id": "F03.07", + "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "services": [ - "APIM" + "Monitor", + "NetworkWatcher" ], "severity": "Medium", - "subcategory": "Performance and scalability", - "text": "Deploy self-hosted gateways where Azure doesn't have a region close to the backend APIs." + "subcategory": "Monitoring", + "text": "Use Network Watcher to proactively monitor traffic flows", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "d7941d4a-7b6f-458f-8714-2f8f8c059ad4", - "link": "https://learn.microsoft.com/azure/api-management/api-management-error-handling-policies", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", + "id": "F03.08", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "services": [ - "AzurePolicy", - "APIM" + "Monitor" ], "severity": "Medium", - "subcategory": "Development best practices", - "text": "Implement an error handling policy at the global level" + "subcategory": "Monitoring", + "text": "Use resource locks to prevent accidental deletion of critical shared services.", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "0b0c0765-ff37-4369-90bd-3eb23ce71b08", - "link": "https://learn.microsoft.com/azure/api-management/set-edit-policies?tabs=form#use-base-element-to-set-policy-evaluation-order", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", + "id": "F03.09", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "AzurePolicy", - "APIM" + "Monitor", + "RBAC", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Development best practices", - "text": "Ensure all APIs policies include a element." + "severity": "Low", + "subcategory": "Monitoring", + "text": "Use deny policies to supplement Azure role assignments. The combination of deny policies and Azure role assignments ensures the appropriate guardrails are in place to enforce who can deploy and configure resources and what resources they can deploy and configure.", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "a5c45b03-93b6-42fe-b16b-8fccb6a79902", - "link": "https://learn.microsoft.com/azure/api-management/policy-fragments", - "services": [ - "ACR", - "AzurePolicy", - "APIM" + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", + "id": "F03.10", + "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", + "services": [ + "Monitor" ], "severity": "Medium", - "subcategory": "Development best practices", - "text": "Use Policy Fragments to avoid repeating same policies definitions across multiple APIs" + "subcategory": "Monitoring", + "text": "Include service and resource health events as part of the overall platform monitoring solution. Tracking service and resource health from the platform perspective is an important component of resource management in Azure.", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "c3818a95-6ff3-4474-88dc-e809b46dad6a", - "link": "https://learn.microsoft.com/azure/api-management/monetization-support", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", + "id": "F03.11", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "services": [ - "APIM" + "Monitor" ], "severity": "Medium", - "subcategory": "Monetization", - "text": "If you are planning to monetize your APIs, review the 'monetization support' article for best practices" + "subcategory": "Monitoring", + "text": "Include alerts and action groups as part of the Azure Service Health platform to ensure that alerts or issues can be actioned", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "a7d0840a-c8c4-4e83-adec-5ca578eb4049", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-use-azure-monitor#resource-logs", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", + "id": "F03.12", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "services": [ - "Monitor", - "APIM" + "Monitor" ], - "severity": "High", + "severity": "Medium", "subcategory": "Monitoring", - "text": "Enable Diagnostics Settings to export logs to Azure Monitor" + "text": "Don't send raw log entries back to on-premises monitoring systems. Instead, adopt a principle that data born in Azure stays in Azure. If on-premises SIEM integration is required, then send critical alerts instead of logs.", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "8691fa38-45ed-4299-a247-fecd98d35deb", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-app-insights", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "9945bda4-3334-4f24-a116-34182ba52752", + "id": "F03.13", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ "Monitor", - "APIM" + "RBAC", + "Entra" ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Enable Application Insights for more detailed telemetry" + "text": "Use a centralized Azure Monitor Log Analytics workspace to collect logs and metrics from IaaS and PaaS application resources and control log access with Azure RBAC.", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "55fd27bb-76ac-4a91-bc37-049e885be6b7", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-use-azure-monitor", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", + "id": "F03.14", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "services": [ - "Monitor", - "APIM" + "Monitor" ], - "severity": "High", + "severity": "Medium", "subcategory": "Monitoring", - "text": "Configure alerts on the most critical metrics" + "text": "Use Azure Monitor Logs for insights and reporting.", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure API Management Review", - "guid": "39460bdb-156f-4dc2-a87f-1e8c11ab0998", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#certificate-management-in-azure-key-vault", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", + "id": "F03.15", + "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "services": [ - "Entra", - "AKV", - "APIM" + "Monitor", + "Storage" ], - "severity": "High", - "subcategory": "Data protection", - "text": "Ensure that custom SSL certificates are stored an Azure Key Vault so they can be securely accessed and updated" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage.", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure API Management Review", - "guid": "e9217997-5f6c-479d-8576-8f2adf706ec8", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#azure-ad-authentication-required-for-data-plane-access", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "97be9951-9048-4384-9c98-6cb2913156a1", + "id": "F03.16", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "services": [ - "Entra", - "APIM" + "Monitor" ], - "severity": "High", - "subcategory": "Identity", - "text": "Protect incoming requests to APIs (data plane) with Azure AD" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Monitor alerts for the generation of operational alerts.", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure API Management Review", - "guid": "5e5f64ba-c90e-480e-8888-398d96cf0bfb", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-aad", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "859c3900-4514-41eb-b010-475d695abd74", + "id": "F03.17", + "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "services": [ - "Entra", - "APIM" + "Monitor" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Use Azure AD to authenticate users in the Developer Portal" + "subcategory": "Monitoring", + "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure API Management Review", - "guid": "f8e574ce-280f-49c8-b2ef-68279b081cf3", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-create-groups", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", + "id": "F03.18", + "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "services": [ - "Entra", - "APIM" + "Monitor" ], "severity": "Medium", - "subcategory": "Privileged access", - "text": "Create appropriate groups to control the visibility of the products" + "subcategory": "Monitoring", + "text": "Consider supported regions for linked Log Analytics workspace and automation accounts", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure API Management Review", - "guid": "cd45c90e-7690-4753-930b-bf290c69c074", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#virtual-network-integration", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", + "id": "F04.01", + "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "services": [ - "VNet", - "APIM" + "VM", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Security", - "text": "Deploy the service within a Virtual Network (VNET)" + "subcategory": "Operational compliance", + "text": "Use Azure policies to automatically deploy software configurations through VM extensions and enforce a compliant baseline VM configuration.", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure API Management Review", - "guid": "02661582-b3d1-48d1-9d7b-c6a918a0ca33", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#network-security-group-support", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "description": "Azure Policy's guest configuration features can audit and remediate machine settings (e.g., OS, application, environment) to ensure resources align with expected configurations, and Update Management can enforce patch management for VMs.", + "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", + "id": "F04.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "services": [ - "VNet", "Monitor", - "APIM" + "VM", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Security", - "text": "Deploy network security groups (NSG) to your subnets to restrict or monitor traffic" + "subcategory": "Operational compliance", + "text": "Monitor VM security configuration drift via Azure Policy.", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure API Management Review", - "guid": "67437a28-2721-4a2c-becd-caa54c8237a5", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#azure-private-link", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", + "id": "F05.01", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "services": [ - "VNet", - "PrivateLink", - "APIM" + "VM", + "ACR", + "ASR" ], "severity": "Medium", - "subcategory": "Security", - "text": "Deploy Private Endpoints to filter incoming traffic when VNET is not used" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure API Management Review", - "guid": "d698adbd-3288-44cb-b10a-9b572da395ae", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#disable-public-network-access", - "services": [ - "APIM" - ], - "severity": "High", - "subcategory": "Security", - "text": "Disable Public Network Access" + "subcategory": "Protect and Recover", + "text": "Use Azure Site Recovery for Azure-to-Azure Virtual Machines disaster recovery scenarios. This enables you to replicate workloads across regions.", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure API Management Review", - "guid": "7519e385-a88b-4d34-966b-6269d686e890", - "link": "https://learn.microsoft.com/azure/api-management/front-door-api-management", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", + "id": "F05.02", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "services": [ - "FrontDoor", - "APIM" + "ASR" ], "severity": "Medium", - "subcategory": "Connectivity", - "text": "Use Azure Front Door for multi-region deployment" + "subcategory": "Protect and Recover", + "text": "Ensure to use and test native PaaS service disaster recovery capabilities.", + "waf": "Operations" }, { - "category": "Platform automation and DevOps", - "checklist": "Azure API Management Review", - "guid": "0674d750-0c6f-4ac0-8717-ceec04d0bdbd", - "link": "https://learn.microsoft.com/azure/api-management/automation-manage-api-management", + "category": "Management", + "checklist": "Azure Landing Zone Review", + "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", + "id": "F05.03", + "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "services": [ - "APIM" + "Backup" ], "severity": "Medium", - "subcategory": "Automation", - "text": "Simplify management with PowerShell automation scripts" + "subcategory": "Protect and Recover", + "text": "Use Azure-native backup capabilities, or an Azure-compatible, 3rd-party backup solution.", + "waf": "Operations" }, { - "category": "Platform automation and DevOps", - "checklist": "Azure API Management Review", - "guid": "c385bfcd-49fd-4786-81ba-cedbb4c57345", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/app-platform/api-management/platform-automation-and-devops#design-recommendations", + "ammp": true, + "category": "Management ", + "checklist": "Azure Landing Zone Review", + "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", + "id": "F06.01", + "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "services": [ - "Entra", - "APIM" + "VM" ], - "severity": "Medium", - "subcategory": "Best practices", - "text": "Review DevOps best practices from the Cloud Adaption Framework APIM Landing Zone Accelerator" + "severity": "High", + "subcategory": "Fault Tolerance", + "text": "Leverage Availability Zones for your VMs in regions where they are supported.", + "waf": "Reliability" }, { - "category": "Platform automation and DevOps", - "checklist": "Azure API Management Review", - "guid": "6c3a27c0-197f-426c-9ffa-86fed51d9ab6", - "link": "https://learn.microsoft.com/azure/api-management/visual-studio-code-tutorial", + "ammp": true, + "category": "Management ", + "checklist": "Azure Landing Zone Review", + "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "services": [ - "Entra", - "APIM" + "VM" ], - "severity": "Medium", - "subcategory": "Best practices", - "text": "Promote usage of Visual Studio Code APIM extension for faster API development" + "severity": "High", + "subcategory": "Fault Tolerance", + "text": "Avoid running a production workload on a single VM.", + "waf": "Reliability" }, { - "category": "Platform automation and DevOps", - "checklist": "Azure API Management Review", - "guid": "354f1c03-8112-4965-85ad-c0074bddf231", - "link": "https://learn.microsoft.com/azure/api-management/devops-api-development-templates", + "category": "Management ", + "checklist": "Azure Landing Zone Review", + "guid": "84101f59-1941-4195-a270-e28034290e3a", + "id": "F06.03", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "services": [ - "APIM" + "LoadBalancer", + "ACR", + "AppGW" ], "severity": "Medium", - "subcategory": "DevOps", - "text": "Implement DevOps and CI/CD in your workflow" + "subcategory": "Fault Tolerance", + "text": "Azure Load Balancer and Application Gateway distribute incoming network traffic across multiple resources.", + "waf": "Reliability" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "b6439493-426a-45f3-9697-cf65baee208d", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-mutual-certificates-for-clients", - "services": [ - "APIM" - ], + "checklist": "Azure Landing Zone Review", + "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", + "id": "G01.01", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "services": [], "severity": "Medium", - "subcategory": "APIs", - "text": "Secure APIs using client certificate authentication" + "subcategory": "Access control", + "text": "Determine the incident response plan for Azure services before allowing it into production.", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "2a67d143-1033-4c0a-8732-680896478f08", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-mutual-certificates", - "services": [ - "APIM" - ], + "checklist": "Azure Landing Zone Review", + "guid": "01365d38-e43f-49cc-ad86-8266abca264f", + "id": "G01.02", + "link": "https://www.microsoft.com/security/business/zero-trust", + "services": [], "severity": "Medium", - "subcategory": "APIs", - "text": "Secure backend services using client certificate authentication" + "subcategory": "Access control", + "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate.", + "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure API Management Review", - "guid": "074435f5-4a46-41ac-b521-d6114cb5d845", - "link": "https://learn.microsoft.com/azure/api-management/mitigate-owasp-api-threats", + "checklist": "Azure Landing Zone Review", + "guid": "5017f154-e3ab-4369-9829-e7e316183687", + "id": "G02.01", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "services": [ - "APIM" + "AKV" ], - "severity": "Medium", - "subcategory": "APIs", - "text": "Review 'Recommendations to mitigate OWASP API Security Top 10 threats' article and check what is applicable to your APIs" + "severity": "High", + "subcategory": "Encryption and keys", + "text": "Use Azure Key Vault to store your secrets and credentials", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "5507c4b8-a7f8-41d6-9661-418c987100c9", - "link": "https://learn.microsoft.com/azure/api-management/authorizations-overview", + "checklist": "Azure Landing Zone Review", + "graph": "ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1)", + "guid": "a0477a20-9945-4bda-9333-4f2491163418", + "id": "G02.02", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "services": [ - "APIM" + "AKV" ], "severity": "Medium", - "subcategory": "APIs", - "text": "Use Authorizations feature to simplify management of OAuth 2.0 token for your backend APIs" + "subcategory": "Encryption and keys", + "text": "Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets.", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "2deee033-b906-4bc2-9f26-c8d3699fe091", - "link": "https://learn.microsoft.com/azure/api-management/api-management-howto-manage-protocols-ciphers", + "checklist": "Azure Landing Zone Review", + "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", + "id": "G02.03", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "APIM" + "AKV", + "AzurePolicy" ], - "severity": "High", - "subcategory": "Ciphers", - "text": "Use the latest TLS version when encrypting information in transit. Disable outdated and unnecessary protocols and ciphers when possible." + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects.", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "f8af3d94-1d2b-4070-846f-849197524258", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#im-8-restrict-the-exposure-of-credential-and-secrets", + "checklist": "Azure Landing Zone Review", + "guid": "dc055bcf-619e-48a1-9f98-879525d62688", + "id": "G02.04", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ "AKV", - "APIM" + "RBAC", + "Entra" ], - "severity": "High", - "subcategory": "Data protection", - "text": "Ensure that secrets (Named values) are stored an Azure Key Vault so they can be securely accessed and updated" + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Follow a least privilege model by limiting authorization to permanently delete keys, secrets, and certificates to specialized custom Microsoft Entra ID roles.", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "791abd8b-7706-4e31-9569-afefde724be3", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#managed-identities", + "checklist": "Azure Landing Zone Review", + "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "G02.05", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "APIM" + "AKV" ], "severity": "Medium", - "subcategory": "Identities", - "text": "Use managed identities to authenticate to other Azure resources whenever possible" + "subcategory": "Encryption and keys", + "text": "Automate the certificate management and renewal process with public certificate authorities to ease administration.", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure API Management Review", - "guid": "220c4ca6-6688-476b-b2b5-425a78e6fb87", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/api-management-security-baseline?toc=%2Fazure%2Fapi-management%2F&bc=%2Fazure%2Fapi-management%2Fbreadcrumb%2Ftoc.json#ns-6-deploy-web-application-firewall", + "checklist": "Azure Landing Zone Review", + "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "G02.06", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "WAF", - "Entra", - "AppGW", - "APIM" + "AKV" ], - "severity": "High", - "subcategory": "Network", - "text": "Use web application firewall (WAF) by deploying Application Gateway in front of APIM" + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Establish an automated process for key and certificate rotation.", + "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Use Azure Key Vault to store any secrets the application needs. Key Vault provides a safe and audited environment for storing secrets and is well-integrated with App Service through the Key Vault SDK or App Service Key Vault References.", - "guid": "834ac932-223e-4ce8-8b12-3071a5416415", - "id": "A01.01", - "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", + "checklist": "Azure Landing Zone Review", + "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", + "id": "G02.07", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "AppSvc", - "AKV" + "AKV", + "VNet", + "PrivateLink" ], - "severity": "High", - "subcategory": "Data Protection", - "text": "Use Key Vault to store secrets", + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Enable firewall and virtual network service endpoint or private endpoint on the vault to control access to the key vault.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Use a Managed Identity to connect to Key Vault either using the Key Vault SDK or through App Service Key Vault References.", - "guid": "833ea3ad-2c2d-4e73-8165-c3acbef4abe1", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", + "checklist": "Azure Landing Zone Review", + "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", + "id": "G02.08", + "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", "services": [ - "AppSvc", - "Entra", - "AKV" + "Monitor", + "AKV", + "Entra" ], - "severity": "High", - "subcategory": "Data Protection", - "text": "Use Managed Identity to connect to Key Vault", + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Use the platform-central Azure Monitor Log Analytics workspace to audit key, certificate, and secret usage within each instance of Key Vault.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Store the App Service TLS certificate in Key Vault.", - "guid": "f8d39fda-4776-4831-9c11-5775c2ea55b4", - "id": "A01.03", - "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-certificate", + "checklist": "Azure Landing Zone Review", + "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", + "id": "G02.09", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "AppSvc", - "AKV" + "AKV", + "AzurePolicy" ], - "severity": "High", - "subcategory": "Data Protection", - "text": "Use Key Vault to store TLS certificate.", + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Delegate Key Vault instantiation and privileged access and use Azure Policy to enforce a consistent compliant configuration.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Systems that process sensitive information should be isolated. To do so, use separate App Service Plans or App Service Environments and consider the use of different subscriptions or management groups.", - "guid": "6ad48408-ee72-4734-a475-ba18fdbf590c", - "id": "A01.04", - "link": "https://learn.microsoft.com/azure/app-service/overview-hosting-plans", - "services": [ - "AppSvc", - "Subscriptions" + "checklist": "Azure Landing Zone Review", + "guid": "16183687-a047-47a2-8994-5bda43334f24", + "id": "G02.10", + "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", + "services": [ + "AKV" ], "severity": "Medium", - "subcategory": "Data Protection", - "text": "Isolate systems that process sensitive information", + "subcategory": "Encryption and keys", + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Local disks on App Service are not encrypted and sensitive data should not be stored on those. (For example: D:\\\\Local and %TMP%).", - "guid": "e65de8e0-3f9b-4cbd-9682-66abca264f9a", - "id": "A01.05", - "link": "https://learn.microsoft.com/azure/app-service/operating-system-functionality#file-access", + "checklist": "Azure Landing Zone Review", + "guid": "91163418-2ba5-4275-8694-4008be7d7e48", + "id": "G02.11", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "AppSvc", - "TrafficManager" + "AKV" ], "severity": "Medium", - "subcategory": "Data Protection", - "text": "Do not store sensitive data on local disk", + "subcategory": "Encryption and keys", + "text": "Use an Azure Key Vault per application per environment per region.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "For authenticated web application, use a well established Identity Provider like Azure AD or Azure AD B2C. Leverage the application framework of your choice to integrate with this provider or use the App Service Authentication / Authorization feature.", - "guid": "919ca0b2-c121-459e-814b-933df574eccc", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/app-service/overview-authentication-authorization", + "checklist": "Azure Landing Zone Review", + "guid": "25d62688-6d70-4ba6-a97b-e99519048384", + "id": "G02.12", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "AppSvc", - "Entra" + "AKV", + "ACR", + "ASR" ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Use an established Identity Provider for authentication", + "subcategory": "Encryption and keys", + "text": "If you want to bring your own keys, this might not be supported across all considered services. Implement relevant mitigation so that inconsistencies don't hinder desired outcomes. Choose appropriate region pairs and disaster recovery regions that minimize latency.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Deploy code to App Service from a controlled and trusted environment, like a well-managed and secured DevOps deployment pipeline. This avoids code that was not version controlled and verified to be deployed from a malicious host.", - "guid": "3f9bcbd4-6826-46ab-aa26-4f9a19aed9c5", - "id": "A02.02", - "link": "https://learn.microsoft.com/azure/app-service/deploy-best-practices", + "checklist": "Azure Landing Zone Review", + "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", + "id": "G03.01", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "services": [ - "AppSvc", "Entra" ], - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Deploy from a trusted environment", + "severity": "Medium", + "subcategory": "Operations", + "text": "Use Microsoft Entra ID reporting capabilities to generate access control audit reports.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Disable basic authentication for both FTP/FTPS and for WebDeploy/SCM. This disables access to these services and enforces the use of Azure AD secured endpoints for deployment. Note that the SCM site can also be opened using Azure AD credentials.", - "guid": "5d04c2c3-919c-4a0b-8c12-159e114b933d", - "id": "A02.03", - "link": "https://learn.microsoft.com/azure/app-service/deploy-configure-credentials#disable-basic-authentication", + "checklist": "Azure Landing Zone Review", + "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", + "id": "G03.02", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "services": [ - "Entra" + "ARS", + "Storage", + "Monitor" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Export Azure activity logs to Azure Monitor Logs for long-term data retention. Export to Azure Storage for long-term storage beyond two years, if necessary.", + "waf": "Security" + }, + { + "ammp": true, + "category": "Security", + "checklist": "Azure Landing Zone Review", + "guid": "09945bda-4333-44f2-9911-634182ba5275", + "id": "G03.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", + "services": [ + "Defender", + "Subscriptions" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable basic authentication", + "subcategory": "Operations", + "text": "Enable Defender Cloud Security Posture Management for all subscriptions.", "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure App Security Review", - "description": "Where possible use Managed Identity to connect to Azure AD secured resources. If this is not possible, store secrets in Key Vault and connect to Key Vault using a Managed Identity instead.", - "guid": "f574eccc-d9bd-43ba-bcda-3b54eb2eb03d", - "id": "A02.04", - "link": "https://learn.microsoft.com/azure/app-service/overview-managed-identity?tabs=portal%2Chttp", + "checklist": "Azure Landing Zone Review", + "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", + "id": "G03.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", "services": [ - "Entra", - "AKV" + "Defender", + "Subscriptions" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Use Managed Identity to connect to resources", + "subcategory": "Operations", + "text": "Enable a Defender Cloud Workload Protection Plan for Servers on all subscriptions.", "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure App Security Review", - "description": "Where using images stored in Azure Container Registry, pull these using a Managed Identity.", - "guid": "d9a25827-18d2-4ddb-8072-5769ee6691a4", - "id": "A02.05", - "link": "https://learn.microsoft.com/azure/app-service/configure-custom-container#use-managed-identity-to-pull-image-from-azure-container-registry", + "checklist": "Azure Landing Zone Review", + "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", + "id": "G03.05", + "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", "services": [ - "Entra", - "ACR" + "Defender", + "Subscriptions" ], "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Pull containers using a Managed Identity", + "subcategory": "Operations", + "text": "Enable Defender Cloud Workload Protection Plans for Azure Resources on all subscriptions.", "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure App Security Review", - "description": "By configuring the diagnostic settings of App Service, you can send all telemetry to Log Analytics as the central destination for logging and monitoring. This allows you to monitor runtime activity of App Service such as HTTP logs, application logs, platform logs, ...", - "guid": "47768314-c115-4775-a2ea-55b46ad48408", - "id": "A03.01", - "link": "https://learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs", + "checklist": "Azure Landing Zone Review", + "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", + "id": "G03.06", + "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection", + "services": [], + "severity": "High", + "subcategory": "Operations", + "text": "Enable Endpoint Protection on IaaS Servers.", + "waf": "Security" + }, + { + "category": "Security", + "checklist": "Azure Landing Zone Review", + "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "G03.07", + "link": "https://learn.microsoft.com/azure/security-center/", "services": [ - "AppSvc", - "Entra", + "Defender", "Monitor" ], "severity": "Medium", - "subcategory": "Logging and Monitoring", - "text": "Send App Service runtime logs to Log Analytics", + "subcategory": "Operations", + "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Set up a diagnostic setting to send the activity log to Log Analytics as the central destination for logging and monitoring. This allows you to monitor control plane activity on the App Service resource itself.", - "guid": "ee72734b-475b-4a18-bdbf-590ce65de8e0", - "id": "A03.02", - "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "checklist": "Azure Landing Zone Review", + "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", + "id": "G03.08", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AppSvc", - "Entra", - "Monitor" + "Monitor", + "Entra" ], "severity": "Medium", - "subcategory": "Logging and Monitoring", - "text": "Send App Service activity logs to Log Analytics", + "subcategory": "Operations", + "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace.", "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure App Security Review", - "description": "Control outbound network access using a combination of regional VNet integration, network security groups and UDR's. Traffic should be routed to an NVA such as Azure Firewall. Ensure to monitor the Firewall's logs.", - "guid": "c12159e1-14b9-433d-b574-ecccd9bd3baf", - "id": "A04.01", - "link": "https://learn.microsoft.com/azure/app-service/overview-vnet-integration", + "checklist": "Azure Landing Zone Review", + "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", + "id": "G04.01", + "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", "services": [ - "VNet", - "Firewall", - "NVA", - "Monitor" + "Storage" ], - "severity": "Medium", - "subcategory": "Network Security", - "text": "Outbound network access should be controlled", + "severity": "High", + "subcategory": "Overview", + "text": "Secure transfer to storage accounts should be enabled", "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure App Security Review", - "description": "You can provide a stable outbound IP by using VNet integration and using a VNet NAT Gateway or an NVA like Azure Firewall. This allows the receiving party to allow-list based on IP, should that be needed. Note that for communications towards Azure Services often there's no need to depend on the IP address and mechanics like Service Endpoints should be used instead. (Also the use of private endpoints on the receiving end avoids for SNAT to happen and provides a stable outbound IP range.)", - "guid": "cda3b54e-b2eb-403d-b9a2-582718d2ddb1", - "id": "A04.02", - "link": "https://learn.microsoft.com/azure/app-service/networking/nat-gateway-integration", + "checklist": "Azure Landing Zone Review", + "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", + "id": "G04.02", + "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", "services": [ - "NVA", - "Storage", - "VNet", - "PrivateLink", - "Firewall" + "Storage" ], - "severity": "Low", - "subcategory": "Network Security", - "text": "Ensure a stable IP for outbound communications towards internet addresses", + "severity": "High", + "subcategory": "Overview", + "text": "Enable container soft delete for the storage account to recover a deleted container and its contents.", "waf": "Security" }, { + "ammp": true, "category": "Security", - "checklist": "Azure App Security Review", - "description": "Control inbound network access using a combination of App Service Access Restrictions, Service Endpoints or Private Endpoints. Different access restrictions can be required and configured for the web app itself and the SCM site.", - "guid": "0725769e-e669-41a4-a34a-c932223ece80", - "id": "A04.03", - "link": "https://learn.microsoft.com/azure/app-service/networking-features#access-restrictions", + "checklist": "Azure Landing Zone Review", + "guid": "6f704104-85c1-441f-96d3-c9819911645e", + "id": "G05.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning", "services": [ - "AppSvc", - "PrivateLink" + "Entra" ], "severity": "High", - "subcategory": "Network Security", - "text": "Inbound network access should be controlled", + "subcategory": "Secure privileged access", + "text": "Separate privileged admin accounts for Azure administrative tasks.", "waf": "Security" }, { "category": "Security", - "checklist": "Azure App Security Review", - "description": "Protect against malicious inbound traffic using a Web Application Firewall like Application Gateway or Azure Front Door. Make sure to monitor the WAF's logs.", - "guid": "b123071a-5416-4415-a33e-a3ad2c2de732", - "id": "A04.04", - "link": "https://learn.microsoft.com/azure/app-service/networking/app-gateway-with-service-endpoints", + "checklist": "Azure Landing Zone Review", + "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", + "id": "G06.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", + "services": [], + "severity": "Medium", + "subcategory": "Service enablement framework", + "text": "Plan how new azure services will be implemented", + "waf": "Security" + }, + { + "category": "Security", + "checklist": "Azure Landing Zone Review", + "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", + "id": "G06.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", + "services": [], + "severity": "Medium", + "subcategory": "Service enablement framework", + "text": "Plan how service request will be fulfilled for Azure services", + "waf": "Security" + }, + { + "ammp": true, + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", + "services": [], + "severity": "High", + "subcategory": "DevOps Team Topologies", + "text": "Ensure you have a cross functional DevOps Platform Team to build, manage and maintain your Azure Landing Zone architecture.", + "waf": "Operations" + }, + { + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "services": [], + "severity": "Low", + "subcategory": "DevOps Team Topologies", + "text": "Aim to define functions for Azure Landing Zone Platform team.", + "waf": "Operations" + }, + { + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "services": [ + "RBAC" + ], + "severity": "Low", + "subcategory": "DevOps Team Topologies", + "text": "Aim to define functions for application workload teams to be self-sufficient and not require DevOps Platform Team support. Achieve this through the use of custom RBAC role.", + "waf": "Operations" + }, + { + "ammp": true, + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "165eb5e9-b434-448a-9e24-178632186212", + "id": "H01.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "services": [], + "severity": "High", + "subcategory": "DevOps Team Topologies", + "text": "Use a CI/CD pipeline to deploy IaC artifacts and ensure the quality of your deployment and Azure environments.", + "waf": "Operations" + }, + { + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", + "id": "H01.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "services": [], + "severity": "Medium", + "subcategory": "DevOps Team Topologies", + "text": "Include unit tests for IaC and application code as part of your build process.", + "waf": "Operations" + }, + { + "ammp": true, + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "services": [ + "VM", + "AKV" + ], + "severity": "High", + "subcategory": "DevOps Team Topologies", + "text": "Use Key Vault secrets to avoid hard-coding sensitive information such as credentials (virtual machines user passwords), certificates or keys.", + "waf": "Operations" + }, + { + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", + "services": [ + "Storage" + ], + "severity": "Low", + "subcategory": "DevOps Team Topologies", + "text": "Implement automation for File > New > Landing Zone for applications and workloads.", + "waf": "Operations" + }, + { + "ammp": true, + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", + "id": "H02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "services": [], + "severity": "High", + "subcategory": "Development Lifecycle", + "text": "Ensure a version control system is used for source code of applications and IaC developed. Microsoft recommends Git.", + "waf": "Operations" + }, + { + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "services": [], + "severity": "Low", + "subcategory": "Development Lifecycle", + "text": "Follow a branching strategy to allow teams to collaborate better and efficiently manage version control of IaC and application Code. Review options such as Github Flow.", + "waf": "Operations" + }, + { + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", + "id": "H02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "services": [], + "severity": "Medium", + "subcategory": "Development Lifecycle", + "text": "Adopt a pull request strategy to help keep control of code changes merged into branches.", + "waf": "Operations" + }, + { + "ammp": true, + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", + "id": "H03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "services": [], + "severity": "High", + "subcategory": "Development Strategy", + "text": "Leverage Declarative Infrastructure as Code Tools such as Azure Bicep, ARM Templates or Terraform to build and maintain your Azure Landing Zone architecture. Both from a Platform and Application workload perspective.", + "waf": "Operations" + }, + { + "ammp": true, + "category": "Platform Automation and DevOps", + "checklist": "Azure Landing Zone Review", + "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", + "id": "H04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", + "services": [], + "severity": "High", + "subcategory": "Security", + "text": "Integrate security into the already combined process of development and operations in DevOps to mitigate risks in the innovation process.", + "waf": "Operations" + }, + { + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", + "guid": "976f32a7-30d1-6caa-c2a0-207fdc26571b", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "services": [ + "Storage", + "AVS", + "Backup" + ], + "severity": "Medium", + "subcategory": "Backup", + "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", + "waf": "Reliability" + }, + { + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Microsoft backup service", + "guid": "fc8af7a1-c724-e255-c18d-4ca22a6f27f0", + "id": "A02.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "services": [ + "AVS", + "Backup" + ], + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Use MABS as your backup solution", + "waf": "Reliability" + }, + { + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Best practice - this is Backup, not disaster recovery", + "guid": "be28860f-3d29-a79a-1a0e-36f1b23b36ae", + "id": "A02.02", + "link": "Best practice to deploy backup in the same region as your AVS deployment", + "services": [ + "ASR", + "AVS", + "Backup" + ], + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", + "waf": "Reliability" + }, + { + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Best practice - in case AVS is unavailable", + "guid": "4d2f79a5-4ccf-0dfc-557c-49619b99a540", + "id": "A02.03", + "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", "services": [ - "AppSvc", - "Monitor", - "FrontDoor", - "AppGW", - "WAF" + "AVS" ], - "severity": "High", - "subcategory": "Network Security", - "text": "Use a WAF in front of App Service", - "waf": "Security" + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Make sure the WAF cannot be bypassed by locking down access to only the WAF. Use a combination of Access Restrictions, Service Endpoints and Private Endpoints.", - "guid": "165c3acb-ef4a-4be1-b8d3-9fda47768314", - "id": "A04.05", - "link": "https://learn.microsoft.com/azure/app-service/networking-features#access-restrictions", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", + "guid": "ff431c40-962c-5182-d536-0c2f0c4ce9e0", + "id": "A02.04", + "link": "Will Disaster Recovery Site Recovery, HCX Disaster Recovery, SRM or back tools be used?", "services": [ - "PrivateLink", - "WAF" + "AVS" ], - "severity": "High", - "subcategory": "Network Security", - "text": "Avoid for WAF to be bypassed", - "waf": "Security" + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Escalation process with Microsoft in the event of a regional DR", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Set minimum TLS policy to 1.2 in App Service configuration.", - "graph": "appserviceresources | where type =~ 'microsoft.web/sites/config' | extend compliant = (properties.MinTlsVersion>=1.2) | distinct id,compliant", - "guid": "c115775c-2ea5-45b4-9ad4-8408ee72734b", - "id": "A04.06", - "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-tls-versions", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Compare SRM with HCX", + "guid": "f379436d-3051-daa0-01fb-dc4e0e04d677", + "id": "A03.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/disaster-recovery-using-vmware-site-recovery-manager", "services": [ - "AppSvc", - "AzurePolicy" + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Set minimum TLS policy to 1.2", - "waf": "Security" + "subcategory": "Disaster Recovery", + "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Configure App Service to use HTTPS only. This causes App Service to redirect from HTTP to HTTPS. Strongly consider the use of HTTP Strict Transport Security (HSTS) in your code or from your WAF, which informs browsers that the site should only be accessed using HTTPS.", - "graph": "where (type=='microsoft.web/sites' and (kind == 'app' or kind == 'app,linux' )) | extend compliant = (properties.httpsOnly==true) | distinct id,compliant", - "guid": "475ba18f-dbf5-490c-b65d-e8e03f9bcbd4", - "id": "A04.07", - "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-https", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Recovery into Azure instead of Vmware solution", + "guid": "367f71d8-3cf6-51a0-91a5-3db3d570cc19", + "id": "A03.02", + "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", "services": [ - "AppSvc", - "WAF" + "AVS", + "ASR" ], - "severity": "High", - "subcategory": "Network Security", - "text": "Use HTTPS only", - "waf": "Security" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Do not use wildcards in your CORS configuration, as this allows all origins to access the service (thereby defeating the purpose of CORS). Specifically only allow the origins that you expect to be able to access the service.", - "guid": "68266abc-a264-4f9a-89ae-d9c55d04c2c3", - "id": "A04.08", - "link": "https://learn.microsoft.com/azure/app-service/app-service-web-tutorial-rest-api", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Avoid manual tasks as much as possible", + "guid": "ee02ada0-1887-bb3a-b84c-423f45a09ef9", + "id": "A03.03", + "link": "https://docs.microsoft.com/azure/site-recovery/avs-tutorial-prepare-azure", "services": [ - "Storage" + "AVS", + "ASR" ], - "severity": "High", - "subcategory": "Network Security", - "text": "Wildcards must not be used for CORS", - "waf": "Security" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use Automated recovery plans with either of the Disaster solutions,", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Remote debugging must not be turned on in production as this opens additional ports on the service which increases the attack surface. Note that the service does turn of remote debugging automatically after 48 hours.", - "graph": "appserviceresources | where type =~ 'microsoft.web/sites/config' | extend compliant = (properties.RemoteDebuggingEnabled == false) | distinct id,compliant", - "guid": "d9bd3baf-cda3-4b54-bb2e-b03dd9a25827", - "id": "A04.09", - "link": "https://learn.microsoft.com/azure/app-service/configure-common#configure-general-settings", - "services": [], - "severity": "High", - "subcategory": "Network Security", - "text": "Turn off remote debugging", - "waf": "Security" + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Any other datacenter in the same region", + "guid": "0c2b74e5-9c28-780d-1df3-12d3de4aaa76", + "id": "A03.04", + "link": "https://docs.microsoft.com/azure/azure-vmware/connect-multiple-private-clouds-same-region", + "services": [ + "AVS", + "ASR" + ], + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Configure a secondary disaster recovery environment", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Enable Defender for App Service. This (amongst other threats) detects communications to known malicious IP addresses. Review the recommendations from Defender for App Service as part of your operations.", - "guid": "18d2ddb1-0725-4769-be66-91a4834ac932", - "id": "A04.10", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-app-service-introduction", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", + "guid": "c2a34ec4-2933-4e6c-dc36-e20e67abbe3f", + "id": "A03.05", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "AppSvc", - "Defender" + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Enable Defender for Cloud - Defender for App Service", - "waf": "Security" + "subcategory": "Disaster Recovery", + "text": "Assign IP ranges unique to each region", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Azure provides DDoS Basic protection on its network, which can be improved with intelligent DDoS Standard capabilities which learns about normal traffic patterns and can detect unusual behavior. DDoS Standard applies to a Virtual Network so it must be configured for the network resource in front of the app, such as Application Gateway or an NVA.", - "guid": "223ece80-b123-4071-a541-6415833ea3ad", - "id": "A04.11", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "category": "BCDR", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "ExpressRoute Global Reach can be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or routing must be done through network virtual appliances?", + "guid": "b44fb6ec-bfc1-3a8e-dba2-ca97f0991d2c", + "id": "A03.06", + "link": "This depends if you have multiple AVS Private Clouds. If so and they are in the same region then use AVS Interconnect. If they are in separate regions then use ExpressRoute Global Reach.", "services": [ + "ExpressRoute", + "AVS", "NVA", - "EventHubs", - "VNet", - "AppGW", - "DDoS", - "WAF" + "ASR" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Enable DDOS Protection Standard on the WAF VNet", - "waf": "Security" + "subcategory": "Disaster Recovery", + "text": "Use Global Reach between DR regions", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Where using images stored in Azure Container Registry, pull these over a virtual network from Azure Container Registry using its private endpoint and the app setting 'WEBSITE_PULL_IMAGE_OVER_VNET'.", - "guid": "2c2de732-165c-43ac-aef4-abe1f8d39fda", - "id": "A04.12", - "link": "https://learn.microsoft.com/azure/app-service/configure-custom-container#use-an-image-from-a-network-protected-registry", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "An ExR Global Reach connection will be established to the ExR circuit, no other connections", + "guid": "a2c12df2-07fa-3edd-2cec-fda0b55fb952", + "id": "B01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", "services": [ - "VNet", - "ACR", - "PrivateLink" + "VWAN", + "AVS" ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Pull containers over a Virtual Network", - "waf": "Security" + "subcategory": "Direct (no vWAN, no H&S)", + "text": "Global Reach to ExR circuit - no Azure resources", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Conduct a penetration test on the web application following the penetration testing rules of engagement.", - "guid": "eb2eb03d-d9a2-4582-918d-2ddb10725769", - "id": "A05.01", - "link": "https://learn.microsoft.com/azure/security/fundamentals/pen-testing", - "services": [], + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use ExR to connect on-premises (other) location to Azure", + "guid": "f62ce162-ba5a-429d-674e-fafa1af5f706", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "services": [ + "ExpressRoute", + "AVS" + ], "severity": "Medium", - "subcategory": "Penetration Testing", - "text": "Conduct a penetration test", - "waf": "Security" + "subcategory": "ExpressRoute", + "text": "Connect to Azure using ExR", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", - "guid": "19aed9c5-5d04-4c2c-9919-ca0b2c12159e", - "id": "A06.01", - "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/devsecops-in-azure", - "services": [], + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use the migration assesment tool and timeline to determine bandwidth required", + "guid": "cf01c73b-1247-0a7a-740c-e1ea29bda340", + "id": "B02.02", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-introduction", + "services": [ + "ExpressRoute", + "AVS" + ], "severity": "Medium", - "subcategory": "Vulnerability Management", - "text": "Deploy validated code", - "waf": "Security" + "subcategory": "ExpressRoute", + "text": "Bandwidth sizing", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure App Security Review", - "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", - "guid": "114b933d-f574-4ecc-ad9b-d3bafcda3b54", - "id": "A06.02", - "link": "https://learn.microsoft.com/azure/app-service/overview-patch-os-runtime", - "services": [], - "severity": "High", - "subcategory": "Vulnerability Management", - "text": "Use up-to-date platforms, languages, protocols and frameworks", - "waf": "Security" + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "What traffic is routed through a firewall, what goes directly into Azure", + "guid": "aab216ee-8941-315e-eada-c7e1f2243bd1", + "id": "B02.03", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "services": [ + "ExpressRoute", + "AVS" + ], + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Traffic routing ", + "waf": "Performance" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "785c2fa5-5b56-4ad4-a408-fe72734c476b", - "id": "01.01.01", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/containers/aks/secure-baseline-aks", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "AVS to ExR circuit, no traffic inspection", + "guid": "1f956e45-f62d-5c95-3a95-3bab718907f8", + "id": "B02.04", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", "services": [ - "AKS" + "ExpressRoute", + "AVS" ], "severity": "Medium", - "subcategory": "Development", - "text": "Use canary or blue/green deployments", - "waf": "Operations" + "subcategory": "ExpressRoute", + "text": "Global Reach ", + "waf": "Performance" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "ab5351f6-383a-45ed-9c5e-b143b16db40a", - "id": "01.01.02", - "link": "https://learn.microsoft.com/azure/aks/use-windows-hpc", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Name of the vNet and a unique address space /24 minimum", + "guid": "91f7a87b-21ac-d712-959c-8df2ba034253", + "id": "B03.01", + "link": "https://learn.microsoft.com/azure/virtual-network/quick-create-portal", "services": [ - "AKS" + "VNet", + "AVS" ], - "severity": "Low", - "subcategory": "Development", - "text": "If required for AKS Windows workloads HostProcess containers can be used", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "VNet name & address space", + "waf": "Performance" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "guid": "a280dcf5-90ce-465d-b8e1-3f9ccbd46926", - "id": "01.01.03", - "link": "https://learn.microsoft.com/azure/azure-functions/functions-kubernetes-keda", - "scale": 1, + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Subnet must be called GatewaySubnet", + "guid": "58a027e2-f37f-b540-45d5-e44843aba26b", + "id": "B03.02", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", "services": [ - "AKS" + "ExpressRoute", + "VPN", + "AVS", + "VNet" ], - "severity": "Low", - "simple": -1, - "subcategory": "Development", - "text": "Use KEDA if running event-driven workloads", + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "Gateway subnet", "waf": "Performance" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "guid": "26886d20-b66c-457b-a591-19bf8e8f5c58", - "id": "01.01.04", - "link": "https://dapr.io/", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create a VPN gateway on the hub Gateway subnet", + "guid": "d4806549-0913-3e79-b580-ac2d3706e65a", + "id": "B03.03", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", "services": [ - "AKS" + "ExpressRoute", + "VPN", + "AVS", + "VNet" ], - "severity": "Low", - "simple": 1, - "subcategory": "Development", - "text": "Use Dapr to ease microservice development", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "VPN Gateway", + "waf": "Performance" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "guid": "3acbe04b-be20-49d3-afda-47778424d116", - "ha": 1, - "id": "01.02.01", - "link": "https://learn.microsoft.com/azure/developer/terraform/create-k8s-cluster-with-tf-and-aks", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create an ExR Gateway in the hub Gateway subnet.", + "guid": "864d7a8b-7016-c769-a717-61af6bfb73d2", + "id": "B03.04", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", "services": [ - "AKS" + "ExpressRoute", + "VPN", + "AVS", + "VNet" ], "severity": "Medium", - "simple": -1, - "subcategory": "Infrastructure as Code", - "text": "Use automation through ARM/TF to create your Azure resources", - "waf": "Operations" + "subcategory": "Hub & Spoke", + "text": "ExR Gateway", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "36cb45e5-7960-4332-9bdf-8cc23318da61", - "ha": 1, - "id": "02.01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "How will Internet traffic be routes, Az Firewall, NVA, Secure Hub, On-Premises firewall?", + "guid": "cc2e11b9-7911-7da1-458c-d7fcef794aad", + "id": "B04.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/enable-public-internet-access", "services": [ - "AKS", - "ASR" + "NVA", + "AVS" ], - "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Schedule and perform DR tests regularly", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Internet", + "text": "Egress point", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "170265f4-bb46-4a39-9af7-f317284797b1", - "ha": 1, - "id": "02.02.01", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Allow remote connectivity to AVS via the portal, specifically to vCenter, NSX-T and HCX", + "guid": "71e68ce3-982e-5e56-0191-01100ad0e66f", + "id": "B05.01", + "link": "https://learn.microsoft.com/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", "services": [ - "AKS", - "LoadBalancer", - "TrafficManager", - "FrontDoor" + "AVS", + "Bastion" ], "severity": "Medium", - "subcategory": "High Availability", - "text": "Use Azure Traffic Manager or Azure Front Door as a global load balancer for region failover", - "waf": "Reliability" + "subcategory": "Jumpbox & Bastion", + "text": "Remote connectivity to AVS", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "graph": "resources | where type=='microsoft.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | distinct id,compliant", - "guid": "578a219a-46be-4b54-9350-24922634292b", - "ha": 1, - "id": "02.02.02", - "link": "https://learn.microsoft.com/azure/aks/availability-zones", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Name the jumpbox and identify the subnet where it will be hosted", + "guid": "6f8e93a2-44b1-bb1d-28a1-4d5b3c2ea857", + "id": "B05.02", + "link": "https://learn.microsoft.com/azure/bastion/tutorial-create-host-portal", "services": [ - "AKS" + "VNet", + "AVS", + "Bastion" ], "severity": "Medium", - "subcategory": "High Availability", - "text": "Use Availability Zones if they are supported in your Azure region", - "waf": "Reliability" + "subcategory": "Jumpbox & Bastion", + "text": "Configure a jumbox and Azure Bastion", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "cost": -2, - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | distinct id,compliant", - "guid": "71d41e36-10cc-457b-9a4b-1410d4395898", - "ha": 2, - "id": "02.02.03", - "link": "https://learn.microsoft.com/azure/aks/uptime-sla", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Provides secure / seamless RDP/SSH connectivity to your vm's directly through the portal.", + "guid": "ba430d58-4541-085c-3641-068c00be9bc5", + "id": "B05.03", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", "services": [ - "AKS" + "VM", + "AVS", + "Bastion" ], - "severity": "High", - "subcategory": "High Availability", - "text": "Use the SLA-backed AKS offering", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Jumpbox & Bastion", + "text": "Security measure allowing RDP access via the portal", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "c1288b3c-6a57-4cfc-9444-51e1a3d3453a", - "ha": 1, - "id": "02.02.04", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Using a VPN to connect to Azure to enable VMware communications (HCX) (not recommended)", + "guid": "9988598f-2a9f-6b12-9b46-488415ceb325", + "id": "B06.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-site-to-site-vpn-gateway", "services": [ - "AKS", - "Cost" + "VPN", + "AVS" ], - "severity": "Low", - "simple": -1, - "subcategory": "High Availability", - "text": "Use Disruption Budgets in your pod and deployment definitions", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "VPN", + "text": "Connect to Azure using a VPN", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "3c763963-7a55-42d5-a15e-401955387e5c", - "ha": 1, - "id": "02.02.05", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-geo-replication", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use the migration assesment tool and timeline to determine bandwidth required (eg 3rd party tool in link)", + "guid": "956ce5e9-a862-fe2b-a50d-a22923569357", + "id": "B06.02", + "link": "https://www.omnicalculator.com/other/data-transfer#:~:text=To%20calculate%20the%20data%20transfer%20speed%3A%201%20Download,measured%20time%20to%20find%20the%20data%20transfer%20speed.", "services": [ - "AKS", - "ACR" + "VPN", + "AVS" ], - "severity": "High", - "subcategory": "High Availability", - "text": "If using a private registry, configure region replication to store images in multiple regions", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "VPN", + "text": "Bandwidth sizing", + "waf": "Performance" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "bc14aea6-e65d-48d9-a3ad-c218e6436b06", - "ha": 1, - "id": "02.03.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "What traffic is routed through a firewall, what goes directly into Azure", + "guid": "e095116f-0bdc-4b51-4d71-b9e469d56f59", + "id": "B06.03", + "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", "services": [ - "AKS" + "VPN", + "AVS" ], - "severity": "High", - "subcategory": "Requirements", - "text": "Define non-functional requirements such as SLAs, RTO (Recovery Time Objective) and RPO (Recovery Point Objective).", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "VPN", + "text": "Traffic routing ", + "waf": "Performance" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "f82cb8eb-8c0a-4a63-a25a-4956eaa8dc4a", - "id": "03.01.01", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/aks/eslz-cost-governance-with-kubecost", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Name and unique address space for the vWAN, name for the vWAN hub", + "guid": "4dc480ac-cecd-39c4-fdc6-680b300716ab", + "id": "B07.01", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-site-to-site-portal#openvwan", "services": [ - "AKS", - "Cost" + "VWAN", + "AVS" ], - "severity": "Low", - "subcategory": "Cost", - "text": "Use an external application such as kubecost to allocate costs to different users", - "waf": "Cost" + "severity": "Medium", + "subcategory": "vWAN hub", + "text": "vWAN name, hub name and address space", + "waf": "Performance" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "4d3dfbab-9924-4831-a68d-fdf0d72f462c", - "id": "03.01.02", - "link": "https://learn.microsoft.com/azure/aks/scale-down-mode", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Select either boh or the appropriate connection type.", + "guid": "51d6affd-8e02-6aea-d3d4-0baf618b3076", + "id": "B07.02", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-point-to-site-portal", "services": [ - "AKS", - "Cost" + "VWAN", + "VPN", + "AVS" ], - "severity": "Low", - "subcategory": "Cost", - "text": "Use scale down mode to delete/delallocate nodes", - "waf": "Cost" + "severity": "Medium", + "subcategory": "vWAN hub", + "text": "ExR and/or VPN gateway provisioned", + "waf": "Performance" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "87e651ea-bc4a-4a87-a6df-c06a4b570ebc", - "id": "03.01.03", - "link": "https://learn.microsoft.com/azure/aks/gpu-multi-instance", + "category": "Connectivity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Add Azure firewall to vWAN (recommended)", + "guid": "e32a4c67-3dc0-c134-1c12-52d46dcbab5b", + "id": "B07.03", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-expressroute-portal", "services": [ - "AKS", - "Cost" + "Firewall", + "VWAN", + "AVS" ], "severity": "Medium", - "subcategory": "Cost", - "text": "When required use multi-instance partioning GPU on AKS Clusters", - "waf": "Cost" + "subcategory": "vWAN hub", + "text": "Secure vWAN", + "waf": "Security" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "2b72a08b-0410-4cd6-9093-e068a5cf27e8", - "id": "03.01.04", - "link": "https://learn.microsoft.com/azure/aks/start-stop-nodepools", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Active directory or other identity provider servers", + "guid": "fbc47fbf-bc96-fa93-ed5d-8c9be63cd5c3", + "id": "C01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", "services": [ - "AKS", - "Cost" + "AVS", + "Entra" ], - "severity": "Low", - "subcategory": "Cost", - "text": "If running a Dev/Test cluster use NodePool Start/Stop", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Access", + "text": "External Identity (user accounts)", + "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==true) | distinct id,compliant", - "guid": "9ca48e4a-85e2-4223-bce8-bb12307ca5f1", - "id": "04.01.01", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Not required for LDAPS, required for Kerberos", + "guid": "b5db7975-f6bb-8ba3-ee5f-e3e805887997", + "id": "C01.02", + "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", "services": [ - "AKS", - "AzurePolicy" + "AVS", + "Entra" ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Use Azure Policy for Kubernetes to ensure cluster compliance", + "subcategory": "Access", + "text": "If using AD domain, ensure Sites & Services has been configured", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "graph": "where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1)", - "guid": "6f158e3e-a3a9-42c2-be7e-2165c3a87af4", - "id": "04.01.02", - "link": "https://learn.microsoft.com/azure/aks/use-system-pools", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Authentication for users, must be secure.", + "guid": "c30749c4-e2af-558c-2eb9-0b6ae84881d1", + "id": "C01.03", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-identity-source-vcenter", "services": [ - "AKS" + "AVS", + "Entra" ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Separate applications from the control plane with user/system nodepools", + "subcategory": "Access", + "text": "Use LDAPS not ldap ( vCenter)", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "a7a1f893-9bda-4477-98f2-4c116775c2ea", - "ha": 1, - "id": "04.01.03", - "link": "https://learn.microsoft.com/azure/aks/use-system-pools", + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Authentication for users, must be secure.", + "guid": "64cb9b5c-9edd-787e-1dd8-2b2338e51635", + "id": "C01.04", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-external-identity-source-nsx-t", "services": [ - "AKS" + "AVS", + "Entra" ], - "severity": "Low", - "simple": -1, - "subcategory": "Compliance", - "text": "Add taint to your system nodepool to make it dedicated", + "severity": "Medium", + "subcategory": "Access", + "text": "Use LDAPS not ldap (NSX-T)", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "55b46a94-8008-4ae7-b7e4-b475b6c8bdbf", - "id": "04.01.04", - "link": "https://learn.microsoft.com/azure/container-registry/", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "CN or SAN names, no wildcards, contains private key - CER or PFX", + "guid": "bec285ab-037e-d629-81d1-f61dac23cd4c", + "id": "C02.01", + "link": "https://youtu.be/4jvfbsrhnEs", "services": [ - "AKS", - "ACR" + "AVS", + "Entra" ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Use a private registry for your images, such as ACR", + "subcategory": "Security", + "text": "Security certificate installed on LDAPS servers ", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "59bce65d-e8a0-43f9-9879-468d66a786d6", - "id": "04.01.05", - "link": "https://learn.microsoft.com/azure/security-center/container-security", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Standard Azure Roles Based Access Controls", + "guid": "4ba394a2-3c33-104c-8e34-2dadaba9cc73", + "id": "C02.02", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity", "services": [ - "AKS" + "RBAC", + "AVS", + "Entra" ], "severity": "Medium", - "subcategory": "Compliance", - "text": "Scan your images for vulnerabilities", + "subcategory": "Security", + "text": "RBAC applied to Azure roles", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "cc639637-a652-42ac-89e8-06965388e9de", - "id": "04.01.06", - "link": "https://learn.microsoft.com/azure/security-center/container-security", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create roles in vCenter required to meet minimum viable access guidelines", + "guid": "b04ca129-83a9-3494-7512-347dd2d766db", + "id": "C02.03", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-identity#view-the-vcenter-server-privileges", "services": [ - "AKS", - "Defender" + "RBAC", + "AVS", + "Entra" ], "severity": "Medium", - "subcategory": "Compliance", - "text": "Use Azure Security Center to detect security posture vulnerabilities", + "subcategory": "Security", + "text": "RBAC model in vCenter", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "42d4aefe-2383-470e-b019-c30df24996b2", - "id": "04.01.07", - "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", + "guid": "8e477d2f-8004-3dd0-93d6-0aece9e1b2fb", + "id": "C02.04", + "link": "Best practice", "services": [ - "AKS" + "RBAC", + "AVS", + "Entra" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "If required configure FIPS", + "severity": "Medium", + "subcategory": "Security", + "text": "CloudAdmin role usage", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "d167dd18-2b0a-4c24-8b99-9a646f8389a7", - "id": "04.01.08", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-cluster-isolation", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", + "guid": "00e0b729-f9be-f600-8c32-5ec0e8f2ed63", + "id": "C03.01", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "AKS" + "RBAC", + "AVS", + "Entra" ], - "severity": "High", - "subcategory": "Compliance", - "text": "Define app separation requirements (namespace/nodepool/cluster)", + "severity": "Medium", + "subcategory": "Security ", + "text": "Is Privileged Identity Management implemented", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "5e3df584-eccc-4d97-a3b6-bcda3b50eb2e", - "id": "04.02.01", - "link": "https://github.com/Azure/secrets-store-csi-driver-provider-azure", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For the Azure VMware Solution PIM roles", + "guid": "0842d45f-41a8-8274-1155-2f6ed554d315", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "services": [ - "AKS", - "AKV" + "RBAC", + "AVS", + "Entra" ], "severity": "Medium", - "simple": -1, - "subcategory": "Secrets", - "text": "Store your secrets in Azure Key Vault with the CSI Secrets Store driver", + "subcategory": "Security ", + "text": "Is Privileged Identity Management audit reporting implemented", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "b03dda6d-58d7-4c89-8ddb-107d5769ae66", - "id": "04.02.02", - "link": "https://learn.microsoft.com/azure/aks/update-credentials", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Best practice, also see Monitoring/Alerts", + "guid": "915cbcd7-0640-eb7c-4162-9f33775de559", + "id": "C03.03", + "link": "Best practice", "services": [ - "AKS", - "AKV" + "Monitor", + "AVS", + "Entra" ], - "severity": "High", - "subcategory": "Secrets", - "text": "If using Service Principals for the cluster, refresh credentials periodically (like quarterly)", + "severity": "Medium", + "subcategory": "Security ", + "text": "Limit use of CloudAdmin account to emergency access only", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "e7ba73a3-0508-4f80-806f-527db30cee96", - "id": "04.02.03", - "link": "https://learn.microsoft.com/azure/aks/use-kms-etcd-encryption", - "security": 1, + "category": "Identity", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Operational procedure", + "guid": "7effa0c0-9172-e8e4-726a-67dbea8be40a", + "id": "C03.04", + "link": "https://learn.microsoft.com/azure/azure-vmware/rotate-cloudadmin-credentials?tabs=azure-portal", "services": [ - "AKS", - "AKV" + "AVS", + "Entra" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "If required add Key Management Service etcd encryption", + "subcategory": "Security ", + "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", "waf": "Security" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "ec8e4e42-0344-41b0-b865-9123e8956d31", - "id": "04.02.04", - "link": "https://learn.microsoft.com/azure/confidential-computing/confidential-nodes-aks-overview", - "security": 1, + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", + "guid": "8f426fd0-d73b-d398-1f6f-df0cbe262a82", + "id": "D01.01", + "link": "https://learn.microsoft.com/azure/azure-arc/vmware-vsphere/overview", "services": [ - "AKS", - "AKV" + "VM", + "AVS", + "Arc" ], - "severity": "Low", - "subcategory": "Secrets", - "text": "If required consider using Confidential Compute for AKS", - "waf": "Security" + "severity": "Medium", + "subcategory": "Operations", + "text": "AVS VM Management (Azure Arc)", + "waf": "Operations" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "c9e95ffe-6dd1-4a17-8c5f-110389ca9b21", - "id": "04.02.05", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-enable", - "security": 1, + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", + "guid": "11dbe773-e380-9191-1418-e886fa7a6fd0", + "id": "D01.02", + "link": "https://docs.microsoft.com/azure/governance/policy/overview", "services": [ - "AKS", - "Defender", - "AKV" + "Monitor", + "AVS", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Consider using Defender for Containers", - "waf": "Security" + "subcategory": "Operations", + "text": "Azure policy", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | distinct id,compliant", - "guid": "ed127dd1-42b0-46b2-8c69-99a646f3389a", - "id": "05.01.01", - "link": "https://learn.microsoft.com/azure/aks/use-managed-identity", + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", + "guid": "1e59c639-9b7e-a60b-5e93-3798c1aff5db", + "id": "D01.03", + "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json#configure-locks", "services": [ - "AKS", - "Entra" + "AVS" ], - "severity": "High", - "simple": 1, - "subcategory": "Identity", - "text": "Use managed identities instead of Service Principals", - "waf": "Security" + "severity": "Medium", + "subcategory": "Operations", + "text": "Resource locks", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | distinct id,compliant", - "guid": "7e42c78e-78c0-46a6-8a21-94956e698dc4", - "id": "05.01.02", - "link": "https://learn.microsoft.com/azure/aks/managed-aad", + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For manual deployments, all configuration and deployments must be documented", + "guid": "8f2c46aa-ca1b-cad3-3ac9-213dfc0a265e", + "id": "D01.04", + "link": "Make sure to create your own runbook on the deployment of AVS.", "services": [ - "AKS", - "Entra" + "AVS" ], "severity": "Medium", - "simple": 1, - "subcategory": "Identity", - "text": "Integrate authentication with AAD (using the managed integration)", - "waf": "Security" + "subcategory": "Operations", + "text": "Run books", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "a2fe27b2-e287-401a-8352-beedf79b488d", - "id": "05.01.03", - "link": "https://learn.microsoft.com/azure/aks/control-kubeconfig-access", - "security": 1, + "category": "Management", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", + "guid": "86b314f9-1f1e-317a-4dfb-cf510ad4a030", + "id": "D01.05", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations", + "services": [ + "AKV", + "AVS" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Naming conventions for auth keys", + "waf": "Operations" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "For automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "guid": "e22a2d99-eb71-7d7c-07af-6d4cdb1d4443", + "id": "E01.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", "services": [ - "AKS", - "Entra" + "Monitor", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "Limit access to admin kubeconfig (get-credentials --admin)", - "waf": "Security" + "subcategory": "Alerts", + "text": "Create warning alerts for critical thresholds ", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "eec4962c-c3bd-421b-b77f-26e5e6b3bec3", - "id": "05.01.04", - "link": "https://learn.microsoft.com/azure/aks/manage-azure-rbac", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "guid": "6d02f159-627d-79bf-a931-fab6d947eda2", + "id": "E01.02", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", "services": [ - "AKS", - "RBAC", - "Entra" + "Monitor", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "Integrate authorization with AAD RBAC", - "waf": "Security" + "subcategory": "Alerts", + "text": "Create critical alert vSAN consumption", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "d4f3537c-1346-4dc5-9027-a71ffe1bd05d", - "ha": 1, - "id": "05.01.05", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-identity", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Provides platform alerts (generated by Microsoft)", + "guid": "1cc97b39-2c7e-246f-6d73-789cfebfe951", + "id": "E01.03", + "link": "https://www.virtualworkloads.com/2021/04/azure-vmware-solution-azure-service-health/", "services": [ - "AKS", - "RBAC", - "Entra" + "Monitor", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Identity", - "text": "Use namespaces for restricting RBAC privilege in Kubernetes", - "waf": "Security" + "severity": "Medium", + "subcategory": "Alerts", + "text": "Configured for Azure Service Health alerts and notifications", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "d2e0d5d7-71d4-41e3-910c-c57b4a4b1410", - "id": "05.01.06", - "link": "https://learn.microsoft.com/azure/aks/workload-identity-migration-sidecar", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", + "guid": "0962606c-e3b4-62a9-5661-e4ffd62a4509", + "id": "E02.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", "services": [ - "AKS", - "Entra" + "Monitor", + "VM", + "Backup", + "AzurePolicy", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "For POD Identity Access Management use Azure AD Workload Identity (preview)", - "waf": "Security" + "subcategory": "Backup", + "text": "Backup policy", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "f4dcf690-1b30-407d-abab-6f8aa780d3a3", - "id": "05.01.07", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#non-interactive-sign-in-with-kubelogin", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Keep in mind the lead time for requesting new nodes", + "guid": "4ec7ccfb-795e-897e-4a84-fd31c04eadc6", + "id": "E03.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", "services": [ - "AKS", - "Entra" + "Monitor", + "AVS", + "AzurePolicy" ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "For AKS non-interactive logins use kubelogin (preview)", - "waf": "Security" + "subcategory": "Capacity", + "text": "Policy around ESXi host density and efficiency", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==true) | distinct id,compliant", - "guid": "b085b1f2-3119-4771-8c9a-bbf4411810ec", - "id": "05.01.08", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Azure Cost Management can be used - one option, put AVS in it's own Subscription. ", + "guid": "7f8f175d-13f4-5298-9e61-0bc7e9fcc279", + "id": "E04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/govern", "services": [ - "AKS", - "Entra" + "Monitor", + "Subscriptions", + "AVS", + "Cost" ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "Disable AKS local accounts", - "waf": "Security" + "subcategory": "Costs", + "text": "Ensure a good cost management process is in place for Azure VMware Solution - ", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "36abb0db-c118-4f4c-9880-3f30f9a2deb6", - "id": "05.01.09", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#configure-just-in-time-cluster-access-with-azure-ad-and-aks", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Create dashboards to enable core Azure VMware Solution monitoring insights", + "guid": "01e689e0-7c6c-b58f-37bd-4d6b9b1b9c74", + "id": "E05.01", + "link": "https://docs.microsoft.com/azure/azure-portal/azure-portal-dashboards", "services": [ - "AKS", - "Entra" + "Monitor", + "AVS", + "NetworkWatcher" ], - "severity": "Low", - "simple": -1, - "subcategory": "Identity", - "text": "Configure if required Just-in-time cluster access", - "waf": "Security" + "severity": "Medium", + "subcategory": "Dashboard", + "text": "Connection monitor dashboard", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "c4d7f4c6-79bf-45d0-aa05-ce8fc717e150", - "id": "05.01.10", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#use-conditional-access-with-azure-ad-and-aks", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Send to an Azure Storage account or Azure EventHub for processing (direct to Log Analytics is pending)", + "guid": "f9afdcc9-649d-d840-9fb5-a3c0edcc697d", + "id": "E06.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", "services": [ - "AKS", - "Entra" + "Storage", + "Monitor", + "AVS" ], - "severity": "Low", - "simple": -1, - "subcategory": "Identity", - "text": "Configure if required AAD conditional access for AKS", - "waf": "Security" + "severity": "Medium", + "subcategory": "Logs & Metrics", + "text": "Configure Azure VMware Solution logging ", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "e1123a7c-a333-4eb4-a120-4ee3f293c9f3", - "id": "05.01.11", - "link": "https://learn.microsoft.com/azure/aks/use-group-managed-service-accounts", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Must be on-premises, implement if available", + "guid": "7cbac8c3-4eda-d5d9-9bda-c6b5abba9fb6", + "id": "E06.02", + "link": "Is vROPS or vRealize Network Insight going to be used? ", "services": [ - "AKS", - "Entra" + "Monitor", + "AVS" ], - "severity": "Low", - "simple": -1, - "subcategory": "Identity", - "text": "If required for Windows AKS workloads configure gMSA ", - "waf": "Security" + "severity": "Medium", + "subcategory": "Logs & Metrics", + "text": "vRealize Operations", + "waf": "Operations" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "1f711a74-3672-470b-b8b8-a2148d640d79", - "id": "05.01.12", - "link": "https://learn.microsoft.com/azure/aks/use-managed-identity#use-a-pre-created-kubelet-managed-identity", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", + "guid": "b243521a-644d-f865-7fb6-21f9019c0dd2", + "id": "E06.03", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", "services": [ - "AKS", - "Entra" + "Monitor", + "VM", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "For finer control consider using a managed Kubelet Identity", - "waf": "Security" + "subcategory": "Logs & Metrics", + "text": "AVS VM logging", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "cbd8ac2a-aebc-4a2a-94da-1dbf3dc99248", - "id": "06.01.01", - "link": "https://azure.github.io/application-gateway-kubernetes-ingress/setup/install-existing/", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Between on-premises to Azure are monitored using 'connection monitor'", + "guid": "2ca97d91-dd36-7229-b668-01036ccc3cd3", + "id": "E07.01", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", "services": [ - "AKS", - "ACR", - "AppGW" + "Monitor", + "VPN", + "ExpressRoute", + "AVS", + "NetworkWatcher" ], "severity": "Medium", - "simple": -1, - "subcategory": "Best practices", - "text": "If using AGIC, do not share an AppGW across clusters", - "waf": "Reliability" + "subcategory": "Network", + "text": "Monitor ExpressRoute and/or VPN connections ", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | distinct id,compliant", - "guid": "8008ae7d-7e4b-4475-a6c8-bdbf59bce65d", - "id": "06.01.02", - "link": "https://learn.microsoft.com/azure/aks/http-application-routing", - "scale": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "To monitor the Azure VMware Solution back-end ExpressRoute connection (Azure native to AVS)", + "guid": "99209143-60fe-19f0-5633-8b5671277ba5", + "id": "E07.02", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", "services": [ - "AKS" + "ExpressRoute", + "Monitor", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Best practices", - "text": "Do not use AKS Application Routing Add-On", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Network", + "text": "Monitor from an Azure native resource to an Azure VMware Solution VM", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | distinct id,compliant", - "guid": "7bacd7b9-c025-4a9d-a5d2-25d6bc5439d9", - "id": "06.01.03", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", - "scale": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "To monitor end-to-end, on-premises to AVS workloads", + "guid": "b9e5867c-57d3-036f-fb1b-3f0a71664efe", + "id": "E07.03", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-create-using-portal", "services": [ - "AKS" + "Monitor", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Best practices", - "text": "For Windows workloads use Accelerated Networking", - "waf": "Performance" + "subcategory": "Network", + "text": "Monitor from an on-premises resource to an Azure VMware Solution VM", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | distinct id,compliant", - "guid": "ba7da7be-9952-4914-a384-5d997cb39132", - "id": "06.01.04", - "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", - "scale": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Track requests to Azure VMware Solution and Azure VMware Solution based workloads", + "guid": "4af7c5f7-e5e9-bedf-a8cf-314b81735962", + "id": "E08.01", + "link": "Firewall logging and alerting rules are configured (Azure Firewall or 3rd party)", "services": [ - "AKS", - "LoadBalancer" + "Monitor", + "AVS" ], - "severity": "High", - "subcategory": "Best practices", - "text": "Use the standard ALB (as opposed to the basic one)", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Security", + "text": "Auditing and logging is implemented for inbound internet ", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "22fbe8d6-9b40-47ef-9011-25bb1a555a6b", - "id": "06.01.05", - "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#add-a-node-pool-with-a-unique-subnet", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", + "guid": "74be60a3-cfac-f057-eda6-3ee087e805d5", + "id": "E08.02", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", "services": [ - "VNet", - "AKS" + "Monitor", + "AVS" ], "severity": "Medium", - "simple": -2, - "subcategory": "Best practices", - "text": "If using Azure CNI, consider using different Subnets for NodePools", - "waf": "Security" + "subcategory": "Security", + "text": "Session monitoring ", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "c3c39c98-6bb2-4c12-859a-114b5e3df584", - "id": "06.02.01", - "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Enable Diagnostic and metric logging on Azure VMware Solution", + "guid": "a434b3b5-f258-0845-cd76-d7df6ef5890e", + "id": "E09.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-vmware-syslogs", "services": [ - "VNet", - "AKS", - "Cost", - "PrivateLink" + "Monitor", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Cost", - "text": "Use Private Endpoints (preferred) or Virtual Network Service Endpoints to access PaaS services from the cluster", - "waf": "Security" + "subcategory": "VMWare", + "text": "Logging and diagnostics", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "e8a03f97-8794-468d-96a7-86d60f96c97b", - "ha": 1, - "id": "06.03.01", - "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering", + "category": "Monitoring", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Monitor AVS workloads (each VM in AVS)", + "guid": "fb00b69a-83ec-ce72-446e-6c23a0cab09a", + "id": "E10.01", + "link": "https://docs.microsoft.com/azure/azure-monitor/agents/agent-windows?tabs=setup-wizard", "services": [ - "AKS", - "VPN" + "Monitor", + "VM", + "AVS" ], "severity": "Medium", - "subcategory": "HA", - "text": "If hybrid connectivity is required, use 2xER or ER+VPN for better availability", - "waf": "Reliability" + "subcategory": "VMware", + "text": "Log Analytics Agents deployed on Azure VMware Solution guest VM workloads", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | distinct id,compliant", - "guid": "a0f61565-9de5-458f-a372-49c831112dbd", - "id": "06.04.01", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Decision on traffic flow", + "guid": "a1354b87-e18e-bf5c-c50b-8ddf0540e971", + "id": "F01.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", "services": [ - "AKS" + "AVS" ], - "severity": "High", - "simple": 1, - "subcategory": "IPAM", - "text": "Choose the best CNI network plugin for your requirements (Azure CNI recommended)", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "North/South routing through Az Firewall or 3rd party ", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "7faf12e7-0943-4f63-8472-2da29c2b1cd6", - "id": "06.04.02", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", - "scale": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", + "guid": "29a8a499-ec31-f336-3266-0895f035e379", + "id": "F01.02", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-hub-and-spoke", "services": [ - "VNet", - "AKS" + "AVS" ], - "severity": "High", - "subcategory": "IPAM", - "text": "If using Azure CNI, size your subnet accordingly considering the maximum number of pods per node", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "East West (Internal to Azure)", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "22f54b29-bade-43aa-b1e8-c38ec9366673", - "id": "06.04.03", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", - "scale": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Requires a 3rd party NVA with Azure Route server - Scenario 2 (see link)", + "guid": "ebd3cc3c-ac3d-4293-950d-cecd8445a523", + "id": "F01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", "services": [ - "AKS" + "NVA", + "ARS", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "IPAM", - "text": "If using Azure CNI, check the maximum pods/node (default 30)", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "ExR without Global Reach", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "description": "For internal apps organizations often open the whole AKS subnet in their firewalls. This opens network access to the nodes too, and potentially to the pods as well (if using Azure CNI). If LoadBalancer IPs are in a different subnet, only this one needs to be available to the app clients. Another reason is that if the IP addresses in the AKS subnet are a scarce resource, consuming its IP addresses for services will reduce the maximum scalability of the cluster .", - "guid": "13c00567-4b1e-4945-a459-c373e7ed6162", - "id": "06.04.04", - "link": "https://learn.microsoft.com/azure/aks/internal-lb", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", + "guid": "ffb5c5ca-bd89-ff1b-8b73-8a54d503d506", + "id": "F01.04", + "link": "https://learn.microsoft.com/azure/route-server/route-server-faq", "services": [ - "VNet", - "AKS" - ], - "severity": "Low", - "simple": -1, - "subcategory": "IPAM", - "text": "If using private-IP LoadBalancer services, use a dedicated subnet (not the AKS subnet)", - "waf": "Security" + "ARS", + "AVS" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "Route server ", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", - "id": "06.04.05", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", - "scale": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Via on-premises, Az Firewall, 3rd Party, NSX-T pubic IP", + "guid": "a4070dad-3def-818d-e9f7-be440d10e7de", + "id": "F02.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-design-public-internet-access", "services": [ - "AKS" + "AVS" ], - "severity": "High", - "subcategory": "IPAM", - "text": "Size the service IP address range accordingly (it is going to limit the cluster scalability)", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Internet", + "text": "Egress point(s)", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "57bf217f-6dc8-481c-81e2-785773e9c00f", - "id": "06.05.01", - "link": "https://learn.microsoft.com/azure/aks/use-byo-cni", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Az Firewall, 3rd party NVA, Application Gateway, Azure Frontdoor ", + "guid": "e942c03d-beaa-3d9f-0526-9b26cd5e9937", + "id": "F02.02", + "link": "Research and choose optimal solution for each application", "services": [ - "AKS" + "NVA", + "AVS", + "FrontDoor", + "AppGW" ], - "severity": "Low", - "simple": -2, - "subcategory": "Operations", - "text": "If required add your own CNI plugin", + "severity": "Medium", + "subcategory": "Internet", + "text": "Internet facing applications", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "4b3bb365-9458-44d9-9ed1-5c8f52890364", - "id": "06.05.02", - "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", + "guid": "e778a2ec-b4d7-1d27-574c-14476b167d37", + "id": "F03.01", + "link": "https://docs.microsoft.com/azure/route-server/route-server-faq#route-server-limits", "services": [ - "AKS" + "ARS", + "AVS" ], - "severity": "Low", - "simple": -2, - "subcategory": "Operations", - "text": "If required configure Public IP per node in AKS", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Routing", + "text": "When route server Route limit understood? ", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "b3808b9f-a1cf-4204-ad01-3a923ce474db", - "id": "06.06.01", - "link": "https://learn.microsoft.com/azure/aks/concepts-network", - "scale": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "(VPN Gateway, AppGW, FrontDoor, Load balancer, VMs (etc) (Remove: enabled on ExR/VPN Gateway subnet in Azure)", + "guid": "66c97b30-81b9-139a-cc76-dd1d94aef42a", + "id": "F04.01", + "link": "https://docs.microsoft.com/azure/ddos-protection/manage-ddos-protection", "services": [ - "AKS" + "VM", + "VNet", + "AppGW", + "VPN", + "FrontDoor", + "LoadBalancer", + "ExpressRoute", + "AVS", + "DDoS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Scalability", - "text": "Use an ingress controller to expose web-based apps instead of exposing them with LoadBalancer-type services", - "waf": "Reliability" + "subcategory": "Security", + "text": "Is DDoS standard protection of public facing IP addresses? ", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "ccb534e7-416e-4a1d-8e93-533b53199085", - "id": "06.06.02", - "link": "https://learn.microsoft.com/azure/aks/nat-gateway", - "scale": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "To manage Azure VMware Solution, vCenter, NSX manager and HCX manager", + "guid": "d43da920-4ecc-a4e9-dd45-a2986ce81d32", + "id": "F04.02", + "link": "Best practice: Bastion or 3rd party tool", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "simple": -1, - "subcategory": "Scalability", - "text": "Use Azure NAT Gateway as outboundType for scaling egress traffic", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Security", + "text": "Use a dedicated privileged access workstation (PAW)", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "8ee9a69a-1b58-4b1e-9c61-476e110a160b", - "id": "06.06.03", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni#dynamic-allocation-of-ips-and-enhanced-subnet-support", - "scale": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use NSX-T for inter-vmware-traffic inspection", + "guid": "a2dac74f-5380-6e39-25e6-f13b99ece51f", + "id": "F05.01", + "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-F6685367-7AA1-4771-927E-ED77727CFDA3.html", "services": [ - "AKS" + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Scalability", - "text": "Use Dynamic allocations of IPs in order to avoid Azure CNI IP exhaustion", - "waf": "Reliability" + "subcategory": "Traffic Inspection", + "text": "East West (Internal to AVS)", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | distinct id,compliant", - "guid": "3b365a91-7ecb-4e48-bbe5-4cd7df2e8bba", - "id": "06.07.01", - "link": "https://learn.microsoft.com/azure/aks/limit-egress-traffic", - "security": 2, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Decision on whether or not to use Secure hub for E/W and Internet traffic - requires Global Reach", + "guid": "3f621543-dfac-c471-54a6-7b2849b6909a", + "id": "F06.01", + "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", "services": [ - "AKS", - "NVA" + "Firewall", + "VWAN", + "AVS" ], - "severity": "High", - "simple": -2, - "subcategory": "Security", - "text": "Filter egress traffic with AzFW/NVA if your security requirements mandate it", + "severity": "Medium", + "subcategory": "Virtual WAN", + "text": "Use Secure Hub (Azure Firewall or 3rd party)", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | distinct id,compliant", - "guid": "c4581559-bb91-463e-a908-aed8c44ce3b2", - "id": "06.07.02", - "link": "https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Decision to route Azure to Azure traffic through Firewall, not E/W between AVS workloads (internal to AVS)", + "guid": "d7af5670-1b39-d95d-6da2-8d660dfbe16b", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/firewall-manager/secure-cloud-network", "services": [ - "AKS" + "VWAN", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Security", - "text": "If using a public API endpoint, restrict the IP addresses that can access it", + "subcategory": "Virtual WAN", + "text": "East West (Internal to Azure)", "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==true) | distinct id, compliant", - "guid": "ecccd979-3b6b-4cda-9b50-eb2eb03dda6d", - "id": "06.07.03", - "link": "https://learn.microsoft.com/azure/aks/private-clusters", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", + "guid": "7d049005-eb35-4a93-50a5-3b31a9f61161", + "id": "G01.01", + "link": "https://docs.microsoft.com/azure/azure-vmware/configure-nsx-network-components-azure-portal", "services": [ - "AKS" + "Subscriptions", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Security", - "text": "Use private clusters if your requirements mandate it", - "waf": "Security" + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Scale out operations planning", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==true) | distinct id, compliant", - "guid": "ce7f2a7c-297c-47c6-adea-a6ff838db665", - "id": "06.07.04", - "link": "https://learn.microsoft.com/azure/aks/use-network-policies", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", + "guid": "7242c1de-da37-27f3-1ddd-565ccccb8ece", + "id": "G01.02", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", "services": [ - "AKS", + "Storage", + "AVS", "AzurePolicy" ], "severity": "Medium", - "simple": -1, - "subcategory": "Security", - "text": "For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used ", - "waf": "Security" + "subcategory": "Automated Scale", + "text": "Scale in operations planning", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | distinct id,compliant", - "guid": "58d7c892-ddb1-407d-9769-ae669ca48e4a", - "id": "06.07.05", - "link": "https://learn.microsoft.com/azure/aks/use-network-policies", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", + "guid": "3233e49e-62ce-97f3-8737-8230e771b694", + "id": "G01.03", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", "services": [ - "AKS", - "AzurePolicy" + "AVS" ], - "severity": "High", - "subcategory": "Security", - "text": "Enable a Kubernetes Network Policy option (Calico/Azure)", - "waf": "Security" + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Scale serialized operations planning", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "85e2223e-ce8b-4b12-907c-a5f16f158e3e", - "id": "06.07.06", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", + "guid": "68161d66-5707-319b-e77d-9217da892593", + "id": "G01.04", + "link": "Best practice (testing)", "services": [ - "AKS", - "AzurePolicy" + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Security", - "text": "Use Kubernetes network policies to increase intra-cluster security", - "waf": "Security" + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Scale rd operations planning", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "a3a92c2d-e7e2-4165-a3a8-7af4a7a1f893", - "id": "06.07.07", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", - "security": 2, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Define and enforce scale in/out maximum limits for your environment in the automations", + "guid": "c32cb953-e860-f204-957a-c79d61202669", + "id": "G01.05", + "link": "Operational planning - understand workload requirements", "services": [ - "AKS", - "WAF" + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Security", - "text": "Use a WAF for web workloads (UIs or APIs)", - "waf": "Security" + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Scale maximum operations planning", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "cost": -2, - "graph": "Resources | where type=~'microsoft.containerservice/managedclusters' | project resourceGroup,name,pools=properties.agentPoolProfiles | mv-expand pools | project subnetId=tostring(pools.vnetSubnetID) | where isnotempty(subnetId) | join (Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,enableDdosProtection=tostring(properties.enableDdosProtection),subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,enableDdosProtection,subnetId=tostring(subnets.id)) on subnetId | distinct id,resourceGroup,name,enableDdosProtection | extend compliant = (enableDdosProtection == 'true')", - "guid": "9bda4776-8f24-4c11-9775-c2ea55b46a94", - "id": "06.07.08", - "link": "https://learn.microsoft.com/azure/virtual-network/ddos-protection-overview", - "security": 2, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", + "guid": "7bd65a5e-7b5d-652d-dbea-fc6f73a42857", + "id": "G01.06", + "link": "https://docs.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-management-and-monitoring", "services": [ - "VNet", - "AKS", - "DDoS" + "Monitor", + "AVS" ], "severity": "Medium", - "subcategory": "Security", - "text": "Use DDoS Standard in the AKS Virtual Network", - "waf": "Security" + "subcategory": "Automated Scale", + "text": "Monitor scaling operations ", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "cost": -2, - "graph": "Resources | where type=~'microsoft.containerservice/managedclusters' | project resourceGroup,name,pools=properties.agentPoolProfiles | mv-expand pools | project subnetId=tostring(pools.vnetSubnetID) | where isnotempty(subnetId) | join (Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,enableDdosProtection=tostring(properties.enableDdosProtection),subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,enableDdosProtection,subnetId=tostring(subnets.id)) on subnetId | distinct id,resourceGroup,name,enableDdosProtection | extend compliant = (enableDdosProtection == 'true')", - "guid": "6c46b91a-1107-4485-ad66-3183e2a8c266", - "id": "06.07.09", - "link": "https://learn.microsoft.com/azure/aks/http-proxy", - "security": 2, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Consider the use of Azure Private-Link when using other Azure Native Services", + "guid": "95e374af-8a2a-2672-7ab7-b4a1be43ada7", + "id": "G02.01", + "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", "services": [ - "AKS" + "AVS", + "PrivateLink" ], - "severity": "Low", - "subcategory": "Security", - "text": "If required add company HTTP Proxy", - "waf": "Security" + "severity": "Medium", + "subcategory": "Networking", + "text": "Private link", + "waf": "Performance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "e9855d04-c3c3-49c9-a6bb-2c12159a114b", - "id": "06.07.10", - "link": "https://learn.microsoft.com/azure/aks/servicemesh-about", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", + "guid": "71eff90d-5ad7-ac60-6244-2a6f7d3c51f2", + "id": "G02.02", + "link": "Best practice", "services": [ - "AKS" + "AVS" ], "severity": "Medium", - "simple": -2, - "subcategory": "Security", - "text": "Consider using a service mesh for advanced microservice communication management", - "waf": "Security" + "subcategory": "Networking", + "text": "Provisioning Vmware VLANs", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "67f7a9ed-5b31-4f38-a3f3-9812b2463cff", - "ha": 1, - "id": "07.01.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-metric-alerts", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "In which region will AVS be deployed", + "guid": "04e3a2f9-83b7-968a-1044-2811811a924b", + "id": "H01.01", + "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", "services": [ - "AKS", - "Monitor" + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Alerting", - "text": "Configure alerts on the most critical metrics (see Container Insights for recommendations)", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Region selected", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "337453a3-cc63-4963-9a65-22ac19e80696", - "ha": 1, - "id": "07.02.01", - "link": "https://learn.microsoft.com/azure/advisor/advisor-get-started", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Are there regulatory or compliance policies in play", + "guid": "e52d1615-9cc6-565c-deb6-743ed7e90f4b", + "id": "H01.02", + "link": "Internal policy or regulatory compliance", "services": [ - "AKS", - "Entra" + "AVS", + "AzurePolicy" ], - "severity": "Low", - "simple": -1, - "subcategory": "Compliance", - "text": "Check regularly Azure Advisor for recommendations on your cluster", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Data residency compliant with selected regions", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "3aa70560-e7e7-4968-be3d-628af35b2ced", - "id": "07.02.03", - "link": "https://learn.microsoft.com/azure/aks/certificate-rotation", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Request through the support blade", + "guid": "92bd5ad6-441f-a983-7aa9-05dd669d760b", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/migrate/concepts-azure-vmware-solution-assessment-calculation", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "simple": 1, - "subcategory": "Compliance", - "text": "Enable AKS auto-certificate rotation", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Request for number of AVS hosts submitted ", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "e189c599-df0d-45a7-9dd4-ce32c1881370", - "id": "07.02.04", - "link": "https://learn.microsoft.com/azure/aks/supported-kubernetes-versions", - "security": 1, + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "PG approval for deployment", + "guid": "28370f63-1cb8-2e35-907f-c5516b6954fa", + "id": "H01.04", + "link": "Support request through portal or get help from Account Team", "services": [ - "AKS" + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Compliance", - "text": "Have a regular process to upgrade your kubernetes version periodically (quarterly, for example), or use the AKS autoupgrade feature", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Region and number of AVS nodes approved", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "6f7c4c0d-4e51-4464-ad24-57ed67138b82", - "id": "07.02.05", - "link": "https://learn.microsoft.com/azure/aks/node-updates-kured", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Portal/subscription/resource providers/ Microsoft.AVS", + "guid": "96c76997-30a6-bb92-024d-f4f93f5f57fa", + "id": "H01.05", + "link": "Done through the subscription/resource providers/ AVS register in the portal", "services": [ - "AKS" + "Subscriptions", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Compliance", - "text": "Use kured for Linux node upgrades in case you are not using node-image upgrade", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Resource provider for AVS registered", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "139c9580-ade3-426a-ba09-cf157d9f6477", - "id": "07.02.06", - "link": "https://learn.microsoft.com/azure/aks/node-image-upgrade", - "security": 1, + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Connectivity, subscription & governanace model", + "guid": "5898e3ff-5e6b-bee1-6f85-22fee261ce63", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/enterprise-scale-landing-zone", "services": [ - "AKS" + "Subscriptions", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Compliance", - "text": "Have a regular process to upgrade the cluster node images periodically (weekly, for example)", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Landing zone architecture", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "0102ce16-ee30-41e6-b882-e52e4621dd68", - "id": "07.02.07", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/bedrock/bedrock-automated-deployments", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "The name of the RG where AVS will exist", + "guid": "d0181fb8-9cb8-bf4b-f5e5-b5f9bf7ae4ea", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "Consider gitops to deploy applications or cluster configuration to multiple clusters", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Resource group name selected", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "d7672c26-7602-4482-85a4-14527fbe855c", - "id": "07.02.08", - "link": "https://learn.microsoft.com/azure/aks/command-invoke", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Each resource created as part of the deployment will also utilize this prefix in the name", + "guid": "0f0d20c2-5a19-726c-de20-0984e070d9d6", + "id": "H01.08", + "link": "Best practice - naming standards", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "Consider using AKS command invoke on private clusters", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Deployment prefix selected", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "31d7aaab-7571-4449-ab80-53d89e89d17b", - "id": "07.02.09", - "link": "https://learn.microsoft.com/azure/aks/node-auto-repair#node-autodrain", - "security": 1, + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "/22 unique non-overlapping IPv4 address space", + "guid": "7fbf2ab7-a36c-5957-c27a-67038557af2a", + "id": "H01.09", + "link": "https://learn.microsoft.com/azure/azure-vmware/tutorial-network-checklist#routing-and-subnet-considerations", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "For planned events consider using Node Auto Drain", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Network space for AVS management layer", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "ed0fda7f-211b-47c7-8b6e-c18873fb473c", - "id": "07.02.10", - "link": "https://learn.microsoft.com/azure/aks/faq", - "security": 1, + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "vNets used by workloads running in AVS (non-stretched)", + "guid": "0c87f999-e517-21ef-f355-f210ad4134d2", + "id": "H01.10", + "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/installation/GUID-4B3860B8-1883-48CA-B2F3-7C2205D91D6D.html", "services": [ - "AKS" + "VNet", + "AVS" ], - "severity": "High", - "subcategory": "Compliance", - "text": "Develop own governance practices to make sure no changes are performed by operators in the node RG (aka 'infra RG')", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Network space for AVS NSX-T segments", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | distinct id,compliant", - "guid": "73b32a5a-67f7-4a9e-b5b3-1f38c3f39812", - "id": "07.02.11", - "link": "https://learn.microsoft.com/azure/aks/cluster-configuration", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Choose AV36, AV36P, AV52, AV36T (AV36T = Trial)", + "guid": "946c8966-f902-6f53-4f37-00847e8895c2", + "id": "H01.11", + "link": "https://azure.microsoft.com/pricing/details/azure-vmware/", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "simple": 1, - "subcategory": "Compliance", - "text": "Use custom Node RG (aka 'Infra RG') name", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "AVS SKU (region dependent)", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "b2463cff-e189-4c59-adf0-d5a73dd4ce32", - "ha": 1, - "id": "07.02.12", - "link": "https://kubernetes.io/docs/setup/release/notes/", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use the Azure migration assessment tool to determine the minimum number of nodes required (consider BCDR as well)", + "guid": "31833808-26ba-9c31-416f-d54a89a17f5d", + "id": "H01.12", + "link": "https://learn.microsoft.com/azure/migrate/how-to-assess", "services": [ - "AKS" + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Do not use deprecated Kubernetes APIs in your YAML manifests", - "waf": "Operations" + "subcategory": "Pre-deployment", + "text": "Number of hosts to be deployed", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "c1881370-6f7c-44c0-b4e5-14648d2457ed", - "ha": 1, - "id": "07.02.13", - "link": "https://learn.microsoft.com/azure-stack/aks-hci/adapt-apps-mixed-os-clusters", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Understand how and if you should be using reserved instances (cost control)", + "guid": "f2b73c4f-3d46-32c9-5df1-5b8dfcd3947f", + "id": "H01.13", + "link": "https://azure.microsoft.com/en-ca/pricing/details/azure-vmware/#:~:text=Azure%20VMware%20Solution%20%20%20%20Instance%20size,TB%20%28all%20NVMe%29%20%20%20N%2FA%20%2Fhour%20", "services": [ - "AKS" + "AVS", + "Cost" ], - "severity": "Low", - "simple": -1, - "subcategory": "Compliance", - "text": "Taint Windows nodes", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Reserverd Instances", + "waf": "Cost" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "67138b82-0102-4ce1-9ee3-01e6e882e52e", - "id": "07.02.14", - "link": "https://learn.microsoft.com/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-20H2%2Cwindows-10-20H2", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", + "guid": "94ac48ab-ade5-3fa7-f800-263feeb97070", + "id": "H01.14", + "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", "services": [ - "AKS" + "AVS", + "ASR" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "Keep windows containers patch level in sync with host patch level", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Capacity ", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "description": "Via Diagnostic Settings at the cluster level", - "guid": "5b56ad48-408f-4e72-934c-476ba280dcf5", - "ha": 1, - "id": "07.02.15", - "link": "https://learn.microsoft.com/azure/aks/monitor-aks", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Identify which of the networking scenarios make ", + "guid": "1f9d4bd5-14b8-928c-b4cb-eb211f9b8de5", + "id": "H01.15", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", "services": [ - "AKS", - "Monitor" + "AVS" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "Send master logs (aka API logs) to Azure Monitor or your preferred log management solution", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Networking & Connectivity See docs describing scenrario 1 through 5", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "64d1a846-e28a-4b6b-9a33-22a635c15a21", - "id": "07.02.16", - "link": "https://learn.microsoft.com/azure/aks/node-pool-snapshot", + "category": "Planning", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", + "guid": "070db19b-8a2a-fd6a-c39b-4488d8780da9", + "id": "H01.16", + "link": "Please Check Partner Ecosystem", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "subcategory": "Compliance", - "text": "If required use nodePool snapshots", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "3rd party application compatibility ", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "c5a5b252-1e44-4a59-a9d2-399c4d7b68d0", - "id": "07.03.01", - "link": "https://learn.microsoft.com/azure/aks/spot-node-pool", + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", + "guid": "70cfbddc-d3d4-9188-77c8-1cabaefef646", + "id": "I01.01", + "link": "General recommendation for storing encryption keys.", "services": [ - "AKS", - "Cost" + "AKV", + "AVS" ], - "severity": "Low", - "simple": -1, - "subcategory": "Cost", - "text": "Consider spot node pools for non time-sensitive workloads", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Encryption", + "text": "Use Azure Key Vault with in-guest encryption ", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==true) | distinct id,compliant", - "guid": "c755562f-2b4e-4456-9b4d-874a748b662e", - "id": "07.03.02", - "link": "https://learn.microsoft.com/azure/aks/concepts-scale", - "scale": 1, + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", + "guid": "c1a81638-18df-0ce9-a73a-4b9a8a8dd392", + "id": "I01.02", + "link": "https://docs.microsoft.com/azure/azure-vmware/concepts-storage#data-at-rest-encryption", "services": [ - "AKS", - "Cost" + "SQL", + "AVS" ], - "severity": "Low", - "simple": -1, - "subcategory": "Cost", - "text": "Consider AKS virtual node for quick bursting", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Encryption", + "text": "Use in-guest encryption", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "6f8389a7-f82c-4b8e-a8c0-aa63a25a4956", - "ha": 1, - "id": "07.04.01", - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", + "guid": "8d0a8f51-8d35-19cd-c2fe-4e3512fb467e", + "id": "I01.03", + "link": "https://docs.microsoft.com/azure/key-vault/general/authentication", "services": [ - "AKS", - "Monitor" + "ExpressRoute", + "AKV", + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Monitoring", - "text": "Monitor your cluster metrics with Container Insights (or other tools like Prometheus)", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Encryption", + "text": "Keyvault use for secrets", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==true) | distinct id,compliant", - "guid": "eaa8dc4a-2436-47b3-9697-15b1752beee0", - "ha": 1, - "id": "07.04.02", - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Older OS security patching configured for workloads running on Azure VMware Solution are eligible for ESU", + "guid": "4f8b20e9-a2a1-f80f-af9b-8aa3b26dca08", + "id": "I02.01", + "link": "https://docs.microsoft.com/windows-server/get-started/extended-security-updates-deploy", "services": [ - "AKS", - "Monitor" + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Monitoring", - "text": "Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch)", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Extended support", + "text": "Ensure extended security update support ", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "4621dd68-c5a5-4be2-bdb1-1726769ef669", - "ha": 1, - "id": "07.04.03", - "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-analyze", + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Use a SIEM/SOAR", + "guid": "9bb22fec-4d00-3b95-7136-e225d0f5c63a", + "id": "I03.01", + "link": "https://learn.microsoft.com/azure/sentinel/overview", "services": [ - "AKS", - "Monitor" + "Sentinel", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "Monitor CPU and memory utilization of the nodes", - "waf": "Operations" + "subcategory": "Investigation", + "text": "Enable Azure Sentinel or 3rd party SIEM ", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "1a4835ac-9422-423e-ae80-b123081a5417", - "ha": 1, - "id": "07.04.04", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "MS Defender For Cloud, for workloads running on Azure VMware Solution", + "guid": "f42b0b09-c591-238a-1580-2de3c485ebd2", + "id": "I04.01", + "link": "https://learn.microsoft.com/azure/azure-vmware/azure-security-integration#prerequisites", "services": [ - "AKS", - "Monitor" + "Defender", + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "If using Azure CNI, monitor % of pod IPs consumed per node", - "waf": "Operations" + "subcategory": "Security", + "text": "Enable Advanced Threat Detection ", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "description": "I/O in the OS disk is a critical resource. If the OS in the nodes gets throttled on I/O, this could lead to unpredictable behavior, typically ending up in node being declared NotReady", - "guid": "415833ea-3ad3-4c2d-b733-165c3acbe04b", - "ha": 1, - "id": "07.04.05", - "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance", + "category": "Security", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Are the applicable policies enabled (compliance baselines added to MDfC)", + "guid": "bcdd2348-3d0e-c6bb-1092-aa4cd1a66d6b", + "id": "I04.02", + "link": "https://docs.microsoft.com/azure/azure-vmware/azure-security-integration", "services": [ - "ServiceBus", - "EventHubs", - "Storage", - "Monitor", - "AKS" + "AVS", + "AzurePolicy" ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "Monitor OS disk queue depth in nodes", - "waf": "Operations" + "subcategory": "Security", + "text": "Policy & Regulatory Compliance", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "be209d39-fda4-4777-a424-d116785c2fa5", - "ha": 1, - "id": "07.04.06", - "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Azure to Azure (E/W), Azure to On-premises), AVS to Internet, AVS to Azure", + "guid": "607c1ca9-da92-ae19-5a4c-eb1e876acbe7", + "id": "J01.01", + "link": "https://techcommunity.microsoft.com/t5/azure-migration-and/firewall-integration-in-azure-vmware-solution/ba-p/2254961#:~:text=Azure%20VMware%20Solution%20customers%20have%20multiple%20security%20options,the%20box%20to%20provide%20East-West%20and%20North-South%20firewalling.", "services": [ - "LoadBalancer", - "AKS", - "NVA", - "Monitor" + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "If not using egress filtering with AzFW/NVA, monitor standard ALB allocated SNAT ports", - "waf": "Operations" + "subcategory": "Firewalls", + "text": "Azure / 3rd party firewall", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "74c2ee76-569b-4a79-a57e-dedf91b022c9", - "ha": 1, - "id": "07.04.07", - "link": "https://learn.microsoft.com/azure/aks/aks-resource-health", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "To allow HCX appliance to connect/sync", + "guid": "1d87925c-c02b-7fde-a425-7e95ad846a27", + "id": "J01.02", + "link": "https://docs.vmware.com/en/VMware-Cloud-on-AWS/services/com.vmware.vmc-aws-networking-security/GUID-2CFE1654-9CC9-4EDB-A625-21317299E559.html", "services": [ - "AKS", - "Monitor" + "AVS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Subscribe to resource health notifications for your AKS cluster", - "waf": "Operations" + "subcategory": "Firewalls", + "text": "Firewalls allow for East/West traffic inside AVS", + "waf": "Security" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "b54eb2eb-03dd-4aa3-9927-18e2edb11726", - "ha": 1, - "id": "07.05.01", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Decision on which tool to use (SRM requires additional license - enables automation & other features)", + "guid": "468b3495-2f6e-b65a-38ef-3ba631bcaa46", + "id": "J02.01", + "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-B842696B-89EF-4183-9C73-B77157F56055.html", "services": [ - "AKS" + "AVS" ], - "severity": "High", - "simple": -1, - "subcategory": "Resources", - "text": "Configure requests and limits in your pod specs", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Networking", + "text": "HCX and/or SRM", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "769ef669-1a48-435a-a942-223ece80b123", - "ha": 1, - "id": "07.05.02", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Read up on requirements for Service Mesh requirements and how HCX ", + "guid": "be2ced52-da08-d366-cf7c-044c19e29509", + "id": "J02.02", + "link": "https://docs.vmware.com/en/VMware-HCX/4.6/hcx-user-guide/GUID-76BCD059-A31A-4041-9105-ACFB56213E7C.html", "services": [ - "AKS" + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Resources", - "text": "Enforce resource quotas for namespaces", - "waf": "Operations" + "subcategory": "Networking", + "text": "Configuring and Managing the HCX Interconnect", + "waf": "Reliability" }, - { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "081a5417-4158-433e-a3ad-3c2de733165c", - "id": "07.05.03", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + { + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "If you are planning on using stretch networks ensure that your on-premises environment requirements", + "guid": "7dcac579-fc5c-5c9c-f1f7-9b1149ff2c37", + "id": "J02.03", + "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-DBDB4D1B-60B6-4D16-936B-4AC632606909.html", "services": [ - "AKS", - "Subscriptions" + "AVS" ], - "severity": "High", - "subcategory": "Resources", - "text": "Ensure your subscription has enough quota to scale out your nodepools", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Networking", + "text": "Restrictions and limitations for network extensions", + "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | distinct id,compliant", - "guid": "90ce65de-8e13-4f9c-abd4-69266abca264", - "ha": 1, - "id": "07.06.01", - "link": "https://learn.microsoft.com/azure/aks/concepts-scale", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Do workloads require MoN?", + "guid": "cf45c0b9-6c4b-3bfb-86c5-62fe54061c73", + "id": "J02.04", + "link": "https://learn.microsoft.com/azure/azure-vmware/vmware-hcx-mon-guidance", "services": [ - "AKS" + "AVS" ], "severity": "Medium", - "subcategory": "Scalability", - "text": "Use the Cluster Autoscaler", + "subcategory": "Networking", + "text": "Mobility optimized networking", "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | distinct id,compliant", - "guid": "831c2872-c693-4b39-a887-a561bada49bc", - "ha": 1, - "id": "07.06.02", - "link": "https://learn.microsoft.com/azure/aks/custom-node-configuration", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Operating system level of Vmware environment", + "guid": "b7cf11f3-b12e-5189-991a-06df5250d2ca", + "id": "J03.01", + "link": "https://learn.microsoft.com/azure/site-recovery/vmware-physical-azure-support-matrix", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "subcategory": "Scalability", - "text": "Customize node configuration for AKS node pools", - "waf": "Performance" + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Support matrix (OS versions etc).", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "faa19bfe-9d55-4d04-a3c4-919ca1b2d121", - "id": "07.06.03", - "link": "https://learn.microsoft.com/azure/aks/concepts-scale", - "scale": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Required that all switches are dynamic", + "guid": "45fe9252-aa1b-4e30-45c6-bc02f3b76acf", + "id": "J03.02", + "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/vsan-network-design-guide/GUID-91E1CD6F-33A6-4AC6-BC22-3E4807296F86.html#:~:text=Migrate%20Management%20Network%201%20Add%20hosts%20to%20the,each%20host.%20...%204%20Finish%20the%20configuration.%20", "services": [ - "AKS" + "AVS" ], "severity": "Medium", - "simple": -1, - "subcategory": "Scalability", - "text": "Use the Horizontal Pod Autoscaler when required", - "waf": "Performance" + "subcategory": "On-premises pre-requisites", + "text": "Standard switches converted to dynamic switches", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "description": "Larger nodes will bring higher performance and features such as ephemeral disks and accelerated networking, but they will increase the blast radius and decrease the scaling granularity", - "guid": "5ae124ba-34df-4585-bcdc-e9bd3bb0cdb3", - "id": "07.06.04", - "link": "https://blog.cloudtrooper.net/2020/10/23/which-vm-size-should-i-choose-as-aks-node/", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "See sections on sizing and capacity in the link.", + "guid": "e9f6d736-ee44-e2ac-e7f9-e361f8c857f3", + "id": "J03.03", + "link": "https://learn.microsoft.com/azure/azure-vmware/plan-private-cloud-deployment", "services": [ - "AKS" + "AVS" ], - "severity": "High", - "subcategory": "Scalability", - "text": "Consider an appropriate node size, not too large or too small", + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Capacity for HCX appliance", "waf": "Performance" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "38800e6a-ae01-40a2-9fbc-ae5a06e5462d", - "id": "07.06.05", - "link": "https://learn.microsoft.com/azure/aks/quotas-skus-regions#service-quotas-and-limits", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Check hardware restrictions to ensure compatibility with AVS/OS ", + "guid": "1be2cdd6-15a7-9a33-aea7-113859035ce9", + "id": "J03.04", + "link": "https://kb.vmware.com/s/article/2007240#:~:text=ESXi%2FESX%20hosts%20and%20compatible%20virtual%20machine%20hardware%20versions,%20Not%20Supported%20%204%20more%20rows", "services": [ - "AKS" + "AVS" ], - "severity": "Low", - "subcategory": "Scalability", - "text": "If more than 5000 nodes are required for scalability then consider using an additional AKS cluster", - "waf": "Performance" + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Hardware compatibility", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "9583c0f6-6083-43f6-aa6b-df7102c901bb", - "id": "07.06.06", - "link": "https://learn.microsoft.com/azure/event-grid/event-schema-aks", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Need to be converted", + "guid": "16ab821a-27c6-b6d3-6042-10dc4d6dfcb7", + "id": "J04.01", + "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.storage.doc/GUID-01D3CF47-A84A-4988-8103-A0487D6441AA.html", "services": [ - "AKS" + "Storage", + "AVS" ], - "severity": "Low", - "subcategory": "Scalability", - "text": "Consider subscribing to EventGrid Events for AKS automation", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Storage", + "text": "VSAN RDM disks are converted - not supported.", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "c5016d8c-c6c9-4165-89ae-673ef0fff19d", - "id": "07.06.07", - "link": "https://learn.microsoft.com/azure/aks/manage-abort-operations", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Need to be converted", + "guid": "eb2f9313-afb2-ab35-aa24-6d97a3cb0611", + "id": "J04.02", + "link": "3rd-Party tools", "services": [ - "AKS" + "Storage", + "VM", + "AVS" ], - "severity": "Low", - "subcategory": "Scalability", - "text": "For long running operation on an AKS cluster consider event termination", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Storage", + "text": "VM with SCSI shared bus are not supported", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "c4e37133-f186-4ce1-aed9-9f1b32f6e021", - "id": "07.06.08", - "link": "https://learn.microsoft.com/azure/aks/use-azure-dedicated-hosts", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Remove Direct IO before migration", + "guid": "3f2a5cff-c8a6-634a-1f1b-53ef9d321381", + "id": "J04.03", + "link": "Contact VMware", "services": [ - "AKS" + "Storage", + "VM", + "AVS" ], - "severity": "Low", - "subcategory": "Scalability", - "text": "If required consider using Azure Dedicated Hosts for AKS nodes", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Storage", + "text": "VM with Direct IO require removing DirectPath device", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "graph": "where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | mvexpand pools | extend compliant = (pools.osDiskType=='Ephemeral') | project id,name=strcat(name,'-',pools.name), resourceGroup, compliant", - "guid": "24367b33-6971-45b1-952b-eee0b9b588de", - "id": "07.07.01", - "link": "https://learn.microsoft.com/azure/aks/cluster-configuration", - "scale": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Cannot migrate clusters ", + "guid": "efc8a311-74f8-0252-c6a0-4bac7610e266", + "id": "J04.04", + "link": "Contact VMware", "services": [ - "AKS", - "Storage" + "Storage", + "AVS" ], - "severity": "High", + "severity": "Medium", "subcategory": "Storage", - "text": "Use ephemeral OS disks", - "waf": "Performance" + "text": "Shared VMDK files are not supported", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", - "id": "07.07.02", - "link": "https://learn.microsoft.com/azure/virtual-machines/disks-types", - "scale": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Convert to a different format", + "guid": "ab6c89cd-a26f-b894-fe59-61863975458e", + "id": "J04.05", + "link": "Contact VMware", "services": [ - "AKS", - "Storage" + "Storage", + "AVS" ], - "severity": "High", + "severity": "Medium", "subcategory": "Storage", - "text": "For non-ephemeral disks, use high IOPS and larger OS disks for the nodes when running many pods/node since it requires high performance for running multiple pods and will generate huge logs with default AKS log rotation thresholds", - "waf": "Performance" + "text": "RDM with 'physical compatibility mode' are not supported.", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "39c486ce-d5af-4062-89d5-18bb5fd795db", - "id": "07.07.03", - "link": "https://learn.microsoft.com/azure/aks/use-ultra-disks", - "scale": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning 'RAID-1 FTT-1' is default with Thin Provisioning", + "guid": "7628d446-6b10-9678-9cec-f407d990de43", + "id": "J04.06", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", "services": [ - "AKS", - "Storage" + "Storage", + "VM", + "AVS", + "AzurePolicy" ], - "severity": "Low", + "severity": "Medium", "subcategory": "Storage", - "text": "For hyper performance storage option use Ultra Disks on AKS", - "waf": "Performance" + "text": "Default storage policy", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "9f7547c1-747d-4c56-868a-714435bd19dd", - "ha": 1, - "id": "07.07.04", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "The default storage policy is set to RAID-1 (Mirroring) FTT-1, with Object Space Reservation set to Thin provisioning.", + "guid": "37fef358-7ab9-43a9-542c-22673955200e", + "id": "J04.07", + "link": "https://learn.microsoft.com/azure/azure-vmware/configure-storage-policy", "services": [ - "SQL", - "AKS", - "Storage" + "Storage", + "VM", + "AVS", + "AzurePolicy" ], "severity": "Medium", - "simple": -1, "subcategory": "Storage", - "text": "Avoid keeping state in the cluster, and store data outside (AzStorage, AzSQL, Cosmos, etc)", - "waf": "Performance" + "text": "Ensure that the appropriate VM template storage policy is used", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "24429eb7-2281-4376-85cc-57b4a4b18142", - "id": "07.07.05", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-storage", - "scale": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", + "guid": "ebebd109-9f9d-d85e-1b2f-d302012843b7", + "id": "J04.08", + "link": "https://learn.microsoft.com/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", "services": [ - "AKS", - "Storage" + "Storage", + "AVS", + "AzurePolicy" ], "severity": "Medium", "subcategory": "Storage", - "text": "If using AzFiles Standard, consider AzFiles Premium and/or ANF for performance reasons", - "waf": "Performance" + "text": "Failure to tolerate policy", + "waf": "Operations" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "83958a8c-2689-4b32-ab57-cfc64546135a", - "ha": 1, - "id": "07.07.06", - "link": "https://learn.microsoft.com/azure/aks/availability-zones#azure-disk-availability-zone-support", + "category": "VMware", + "checklist": "Azure VMware Solution Implementation Checklist", + "description": "ANF can be used to extend storage for Azure VMware Solution,", + "guid": "1be821bd-4f37-216a-3e3d-2a5ac6996863", + "id": "J04.09", + "link": "https://learn.microsoft.com/azure/azure-vmware/netapp-files-with-azure-vmware-solution", "services": [ - "AKS", - "Storage" + "Storage", + "AVS" ], "severity": "Medium", - "simple": -1, "subcategory": "Storage", - "text": "If using Azure Disks and AZs, consider having nodepools within a zone for LRS disk with VolumeBindingMode:WaitForFirstConsumer for provisioning storage in right zone or use ZRS disk for nodepools spanning multiple zones", - "waf": "Performance" + "text": "Use ANF for external storage", + "waf": "Operations" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "41177955-fe8f-430b-ae72-20dc5b6880da", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/overview", + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "32e42e36-11c8-418b-8a0b-c510e43a18a9", + "id": "A01.01", "services": [ + "Subscriptions", + "AVS", "Entra" ], "severity": "High", - "subcategory": "Business", - "text": "Understand what kind of solution you're creating, such as business-to-business (B2B), business-to-consumer (B2C), or your enterprise software, and how tenants are different from users." + "subcategory": "Identity", + "text": "Ensure ADDS domain controller(s) are deployed in the identity subscription in native Azure", + "waf": "Security" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "2d33d1b7-697c-49f9-b944-afbeac0b2c8f", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", - "services": [], - "severity": "High", - "subcategory": "Business", - "text": "Define your tenants. Understand how many tenants you will support initially, and your growth plans." + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", + "id": "A01.02", + "services": [ + "AVS", + "Entra" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "Ensure ADDS sites and services is configured to keep authentication requests from Azure-based resources (including Azure VMware Solution) local to Azure", + "waf": "Security" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "a2111b8b-cc66-4aa2-9da6-c09fa23851b6", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/pricing-models", - "services": [], + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "de3aad1e-7c28-4ec9-9666-b7570449aa80", + "id": "A01.03", + "services": [ + "AVS", + "Entra" + ], "severity": "High", - "subcategory": "Business", - "text": "Define your pricing model and ensure it aligns with your tenants' consumption of Azure resources." + "subcategory": "Identity", + "text": "Ensure that vCenter is connected to ADDS to enable authentication based on 'named user accounts'", + "waf": "Security" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "331e84a6-2d65-4359-92ff-a1870b062995", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/pricing-models", - "services": [], + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "cd289ced-6b17-4db8-8554-61e2aee3553a", + "id": "A01.04", + "services": [ + "AVS", + "Entra" + ], "severity": "Medium", - "subcategory": "Business", - "text": "Understand whether you need to separate your tenants into different tiers. Tiers might have different pricing, features, performance promises, geographic locations, and so forth." + "subcategory": "Identity", + "text": "Ensure that the connection from vCenter to ADDS is using a secure protocol (LDAPS)", + "waf": "Security" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "90516b37-aab1-46ca-95bb-cc14a6a1608b", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", - "services": [], + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "b9d37dac-43bc-46cd-8d79-a9b24604489a", + "id": "A01.05", + "services": [ + "AVS", + "Entra" + ], "severity": "Medium", - "subcategory": "Business", - "text": "Based on your customers' requirements, decide on the tenancy models that are appropriate for various parts of your solution." + "subcategory": "Identity", + "text": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", + "waf": "Security" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "f5d76ae1-7048-4ff5-abba-f1ca799578b9", - "link": "https://learn.microsoft.com/azure/marketplace/plan-saas-offer", + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "53d88e89-d17b-473b-82a5-a67e7a9ed5b3", + "id": "A01.06", + "services": [ + "AVS", + "Entra" + ], + "severity": "High", + "subcategory": "Identity", + "text": "Ensure that NSX-Manager is integrated with an external Identity provider", + "waf": "Security" + }, + { + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "ae0e37ce-e297-411b-b352-caaab79b198d", + "id": "A01.07", "services": [ + "RBAC", + "AVS", "Entra" ], "severity": "Medium", - "subcategory": "Business", - "text": "When you're ready, sell your B2B multitenant solution using the Microsoft Commercial Marketplace." + "subcategory": "Identity", + "text": "Has an RBAC model been created for use within VMware vSphere", + "waf": "Security" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "9e7cedd9-1e05-4aeb-a7b3-01fe695a394c", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/design-checklist", - "services": [], - "severity": "High", - "subcategory": "Reliability", - "text": "Review the Azure Well-Architected Reliability checklist, which is applicable to all workloads." + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "ab81932c-9fc9-4d1b-a780-36f5e6bfbb9e", + "id": "A01.08", + "services": [ + "RBAC", + "AVS", + "Entra" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "RBAC permissions should be granted on ADDS groups and not on specific users", + "waf": "Security" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "e9521a55-2a7c-425c-8f3e-c38fd0c4df75", - "link": "https://learn.microsoft.com/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor", - "services": [], + "category": "Identity", + "checklist": "Azure VMware Solution Design Review", + "guid": "d503547c-c447-4e82-9128-a71f0f1cac6d", + "id": "A01.09", + "services": [ + "RBAC", + "AVS", + "Entra" + ], "severity": "High", - "subcategory": "Reliability", - "text": "Understand the Noisy Neighbor antipattern. Prevent individual tenants from impacting the system's availability for other tenants." + "subcategory": "Identity", + "text": "RBAC permissions on the Azure VMware Solution resource in Azure are 'locked down' to a limited set of owners only", + "waf": "Security" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "2b99cb00-9abb-49b6-b11c-f2af9692f09e", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/overview", - "services": [], - "severity": "Medium", - "subcategory": "Reliability", - "text": "Design your multitenant solution for the level of growth that you expect. But don't overengineer for unrealistic growth." + "category": "Networking", + "checklist": "Azure VMware Solution Design Review", + "guid": "9ef1d5e8-32e4-42e3-911c-818b0a0bc510", + "id": "B01.01", + "link": "https://github.com/Azure/AzureCAT-AVS/tree/main/networking", + "services": [ + "AVS" + ], + "severity": "High", + "subcategory": "Architecture", + "text": "Is the correct Azure VMware Solution connectivity model selected for the customer use case at hand", + "waf": "Performance" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "7a634a0e-1c9d-42b1-aac2-5a5378f103f1", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/business-metrics", - "services": [], - "severity": "Medium", - "subcategory": "Reliability", - "text": "Define service-level objectives (SLOs) and optionally service-level agreements (SLAs) for your solution. SLAs and SLOs should be based on the requirements of your tenants, as well as the composite SLA of the Azure resources in your architecture." + "category": "Networking", + "checklist": "Azure VMware Solution Design Review", + "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "id": "B02.01", + "services": [ + "Monitor", + "VPN", + "ExpressRoute", + "AVS", + "NetworkWatcher" + ], + "severity": "High", + "subcategory": "Monitoring", + "text": "Ensure ExpressRoute or VPN connections from on-premises to Azure are monitored using 'connection monitor'", + "waf": "Operations" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "45beeeaf-fc59-4079-8fca-65d5724abaa7", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", - "services": [], - "severity": "High", - "subcategory": "Reliability", - "text": "Test the scale of your solution. Ensure that it performs well under all levels of load, and that it scales correctly as the number of tenants increases." + "category": "Networking", + "checklist": "Azure VMware Solution Design Review", + "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", + "id": "B02.02", + "services": [ + "Monitor", + "VM", + "ExpressRoute", + "AVS", + "NetworkWatcher" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Ensure a connection monitor is created from an Azure native resource to an Azure VMware Solution virtual machine to monitor the Azure VMware Solution back-end ExpressRoute connection", + "waf": "Operations" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "2ff55551-984b-4606-95eb-bfb9c8b36761", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", - "services": [], + "category": "Networking", + "checklist": "Azure VMware Solution Design Review", + "guid": "25659d35-58fd-4772-99c9-31112d027fe4", + "id": "B02.03", + "services": [ + "Monitor", + "VM", + "AVS", + "NetworkWatcher" + ], "severity": "Medium", - "subcategory": "Reliability", - "text": "Apply chaos engineering principles to test the reliability of your solution." + "subcategory": "Monitoring", + "text": "Ensure a connection monitor is created from an on-premises resource to an Azure VMware Solution virtual machine to monitor end-2-end connectivity", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "8238c038-8eb2-4a02-8bd5-4908c9442c1c", - "link": "https://learn.microsoft.com/security/zero-trust", - "services": [], + "category": "Networking", + "checklist": "Azure VMware Solution Design Review", + "guid": "563b4dc7-4a74-48b6-933a-d1a0916a6649", + "id": "B03.01", + "services": [ + "ARS", + "AVS" + ], "severity": "High", - "subcategory": "Security", - "text": "Apply the Zero Trust and least privilege principles in all layers of your solution." + "subcategory": "Routing", + "text": "When route server is used, ensure no more then 200 routes are propagated from route server to ExR gateway to on-premises (ARS limit). Important when using MoN", + "waf": "Operations" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "92160e00-6894-4102-97e0-615d4ed93c01", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/map-requests", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "6128a71f-0f1c-4ac6-b9ef-1d5e832e42e3", + "id": "C01.01", "services": [ + "RBAC", + "AVS", "Entra" ], "severity": "High", - "subcategory": "Security", - "text": "Ensure that you can correctly map user requests to tenants. Consider including the tenant context as part of the identity system, or by using another means, like application-level tenant authorization." - }, - { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "3c1538b4-5676-4b85-b451-432befb37b4f", - "link": "https://learn.microsoft.com/azure/security/fundamentals/pen-testing", - "services": [], - "severity": "Medium", - "subcategory": "Security", - "text": "Perform ongoing penetration testing and security code reviews." + "subcategory": "Security (identity)", + "text": "Is Privileged Identity Management implemented for roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", + "waf": "Security" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "5fca45ce-cf2d-42c0-a62c-aac92ba31498", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/governance-compliance", - "services": [], + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "c4e2436b-b336-4d71-9f17-960eee0b9b5c", + "id": "C01.02", + "services": [ + "RBAC", + "AVS", + "Entra" + ], "severity": "High", - "subcategory": "Security", - "text": "Understand your tenants' compliance requirements, including data residency and any compliance or regulatory standards that they require you to meet." + "subcategory": "Security (identity)", + "text": "Is Privileged Identity Management audit reporting implemented for the Azure VMware Solution PIM roles", + "waf": "Security" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "30adb90d-83d4-4a2e-986e-327ffe04e7a5", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/domain-names", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "8defc4d7-21d3-41d2-90fb-707ae9eab40e", + "id": "C01.03", "services": [ - "DNS" + "AVS", + "Entra" ], "severity": "High", - "subcategory": "Security", - "text": "Correctly manage domain names and avoid vulnerabilities like dangling DNS and subdomain takeover attacks." + "subcategory": "Security (identity)", + "text": "Limit use of CloudAdmin account to emergency access only", + "waf": "Security" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "72ded36d-c633-4e0d-bd41-799a29da3481", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/service/overview", - "services": [], + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "d329f798-bc17-48bd-a5a0-6ca7144351d1", + "id": "C01.04", + "services": [ + "RBAC", + "AVS", + "Entra" + ], "severity": "Medium", - "subcategory": "Security", - "text": "Follow service-specific guidance for multitenancy." + "subcategory": "Security (identity)", + "text": "Create custom RBAC roles in vCenter to implement a least-privilege model inside vCenter", + "waf": "Security" }, { - "category": "Cost Optimization", - "checklist": "Multitenant architecture", - "guid": "db30a9fc-9b1d-40f3-ab90-01f6a3e87fc8", - "link": "https://learn.microsoft.com/azure/architecture/framework/cost/design-checklist", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "9dd24429-eb72-4281-97a1-51c5bb4e4f18", + "id": "C01.05", "services": [ - "Cost" + "AVS", + "Entra" ], "severity": "Medium", - "subcategory": "Cost Optimization", - "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." + "subcategory": "Security (identity)", + "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials", + "waf": "Security" }, { - "category": "Cost Optimization", - "checklist": "Multitenant architecture", - "guid": "8533af39-52f6-45b6-a9c3-81b2a54a31e0", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/measure-consumption", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "586cb291-ec16-4a1d-876e-f9f141acdce5", + "id": "C01.06", "services": [ - "Cost" + "VM", + "AVS", + "Entra" ], "severity": "High", - "subcategory": "Cost Optimization", - "text": "Ensure you can adequately measure per-tenant consumption and correlate it with your infrastructure costs." + "subcategory": "Security (identity)", + "text": "Use a centralized identity provider to be used for workloads (VM's) running on Azure VMware Solution", + "waf": "Security" }, { - "category": "Cost Optimization", - "checklist": "Multitenant architecture", - "guid": "c851fd44-7cf1-459c-95a4-f6455d75a981", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/cost-management-allocation", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "79377bcd-b375-41ab-8ab0-ead66e15d3d4", + "id": "C02.01", "services": [ - "Monitor", - "Cost" + "AVS" ], "severity": "Medium", - "subcategory": "Cost Optimization", - "text": "Avoid antipatterns. Antipatterns include failing to track costs, tracking costs with unnecessary precision, real-time measurement, and using monitoring tools for billing." + "subcategory": "Security (network)", + "text": "Is East-West traffic filtering implemented within NSX-T", + "waf": "Security" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "0d475a5a-2c0f-47ab-b1e1-701da68d3407", - "link": "https://learn.microsoft.com/azure/architecture/checklist/data-ops", - "services": [], + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "a2adb1c3-d232-46af-825c-a44e1695fddd", + "id": "C02.02", + "services": [ + "Firewall", + "AVS", + "AppGW" + ], "severity": "High", - "subcategory": "Operational Excellence", - "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." - }, - { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "9f7fa7a9-47fc-4f04-81f6-9f9e87571ed3", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenant-lifecycle", - "services": [], - "severity": "Medium", - "subcategory": "Operational Excellence", - "text": "Use automation to manage the tenant lifecycle, such as onboarding, deployment, provisioning, and configuration." - }, - { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "e0bfceed-4f4e-492d-b9f5-898815faa363", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/updates", - "services": [], - "severity": "Medium", - "subcategory": "Operational Excellence", - "text": "Find the right balance for deploying service updates. Consider both your tenants' requirements and your own operational requirements." + "subcategory": "Security (network)", + "text": "Workloads on Azure VMware Solution are not directly exposed to the internet. Traffic is filtered and inspected by Azure Application Gateway, Azure Firewall or 3rd party solutions", + "waf": "Security" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "a3f80518-d428-4c02-b2cc-dfaef47db7e2", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "eace4cb1-deb4-4c65-8c3f-c14eeab36938", + "id": "C02.03", "services": [ - "Monitor" + "AVS" ], "severity": "High", - "subcategory": "Operational Excellence", - "text": "Monitor the health of the overall system, as well as each tenant." + "subcategory": "Security (network)", + "text": "Auditing and logging is implemented for inbound internet requests to Azure VMware Solution and Azure VMware Solution based workloads", + "waf": "Security" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "dfb42da5-f871-4953-9e5c-da6fda3f1411", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "29e3eec2-1836-487a-8077-a2b5945bda43", + "id": "C02.04", "services": [ - "Monitor" + "Monitor", + "AVS" ], "severity": "Medium", - "subcategory": "Operational Excellence", - "text": "Configure and test alerts to notify you when specific tenants are experiencing issues or are exceeding their consumption limits." - }, - { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "c0c72a1b-e34d-4b3d-b808-2e49f51ce47e", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/resource-organization", - "services": [], - "severity": "High", - "subcategory": "Operational Excellence", - "text": "Organize your Azure resources for isolation and scale." + "subcategory": "Security (network)", + "text": "Session monitoring is implemented for outbound internet connections from Azure VMware Solution or Azure VMware Solution based workloads to identify suspicious/malicious activity", + "waf": "Security" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "c5c5e22d-4b51-4cac-a980-f7aac1a4b427", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/deployment-configuration", - "services": [], + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "334fdf91-c234-4182-a652-75269440b4be", + "id": "C02.05", + "services": [ + "VNet", + "VPN", + "ExpressRoute", + "AVS", + "DDoS" + ], "severity": "Medium", - "subcategory": "Operational Excellence", - "text": "Avoid deployment and configuration antipatterns. Antipatterns include running separate versions of the solution for each tenant, hardcoding tenant-specific configurations or logic, and manual deployments." - }, - { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "f0b1fbd8-689c-4ab3-be1d-ad7607d2fbfd", - "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/performance-efficiency", - "services": [], - "severity": "High", - "subcategory": "Performance Efficiency", - "text": "Review the Azure Well-Architected Performance Efficiency checklist, which is applicable to all workloads." - }, - { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "18911c4c-934c-49a8-839a-60c092afce30", - "link": "https://learn.microsoft.com/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor", - "services": [], - "severity": "High", - "subcategory": "Performance Efficiency", - "text": "If you use shared infrastructure, plan for how you'll mitigate Noisy Neighbor concerns. Ensure that one tenant can't reduce the performance of the system for other tenants." + "subcategory": "Security (network)", + "text": "Is DDoS standard protection enabled on ExR/VPN Gateway subnet in Azure", + "waf": "Security" }, { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "6acf7eb5-24a3-47c7-ae87-1196cd96048e", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "3d3e0843-276d-44bd-a015-bcf219e4a1eb", + "id": "C02.06", "services": [ - "Storage" + "AVS" ], "severity": "Medium", - "subcategory": "Performance Efficiency", - "text": "Determine how you'll scale your compute, storage, networking, and other Azure resources to match the demands of your tenants." + "subcategory": "Security (network)", + "text": "Use a dedicated privileged access workstation (PAW) to manage Azure VMware Solution, vCenter, NSX manager and HCX manager", + "waf": "Security" }, { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "ea55400d-f97d-45aa-b71b-34224bf91ed4", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/resource-organization", - "services": [], - "severity": "High", - "subcategory": "Performance Efficiency", - "text": "Consider each Azure resource's scale limits. Organize your resources appropriately, in order to avoid resource organization antipatterns. For example, don't over-architect your solution to work within unrealistic scale requirements." + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "9ccbd869-266a-4cca-874f-aa19bf39d95d", + "id": "C03.01", + "services": [ + "Defender", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security (guest/VM)", + "text": "Enable Advanced Threat Detection (Microsoft Defender for Cloud aka ASC) for workloads running on Azure VMware Solution", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "Azure Service Bus Premium provides encryption of data at rest. If you use your own key, the data is still encrypted using the Microsoft-managed key, but in addition the Microsoft-managed key will be encrypted using the customer-managed key. ", - "guid": "87af4a79-1f89-439b-ba47-768e14c11567", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/configure-customer-managed-key", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "44c7c891-9ca1-4f6d-9315-ae524ba34d45", + "id": "C03.02", "services": [ - "ServiceBus" + "AVS", + "Arc" ], - "severity": "Low", - "subcategory": "Data Protection", - "text": "Use customer-managed key option in data at rest encryption when required", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" + "severity": "Medium", + "subcategory": "Security (guest/VM)", + "text": "Use Azure ARC for Servers to properly govern workloads running on Azure VMware Solution using Azure native technologies (Azure ARC for Azure VMware Solution is not yet available)", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "Communication between a client application and an Azure Service Bus namespace is encrypted using Transport Layer Security (TLS). Azure Service Bus namespaces permit clients to send and receive data with TLS 1.0 and above. To enforce stricter security measures, you can configure your Service Bus namespace to require that clients send and receive data with a newer version of TLS.", - "guid": "5c1ea55b-46a9-448f-b8ae-7d7e4b475b6c", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/transport-layer-security-enforce-minimum-version", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "85e12139-bd7b-4b01-8f7b-95ef6e043e2a", + "id": "C03.03", "services": [ - "ServiceBus" + "SQL", + "AVS" ], - "severity": "Medium", - "subcategory": "Data Protection", - "text": "Enforce a minimum required version of Transport Layer Security (TLS) for requests ", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" + "severity": "Low", + "subcategory": "Security (guest/VM)", + "text": "Ensure workloads on Azure VMware Solution use sufficient data encryption during run-time (like in-guest disk encryption and SQL TDE). (vSAN encryption at rest is default)", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "When you create a Service Bus namespace, a SAS rule named RootManageSharedAccessKey is automatically created for the namespace. This policy has Manage permissions for the entire namespace. It's recommended that you treat this rule like an administrative root account and don't use it in your application. Using AAD as an authentication provider with RBAC is recommended. ", - "guid": "8bcbf59b-ce65-4de8-a03f-97879468d66a", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-sas#shared-access-authorization-policies", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "a3592718-e6e2-4051-9267-6ae46691e883", + "id": "C03.04", "services": [ - "ServiceBus", - "RBAC", - "Entra", - "TrafficManager", - "AzurePolicy" + "AKV", + "AVS" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "Avoid using root account when it is not necessary", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" + "severity": "Low", + "subcategory": "Security (guest/VM)", + "text": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "A Service Bus client app running inside an Azure App Service application or in a virtual machine with enabled managed entities for Azure resources support does not need to handle SAS rules and keys, or any other access tokens. The client app only needs the endpoint address of the Service Bus Messaging namespace. ", - "guid": "786d60f9-6c96-4ad8-a55d-04c2b39c986b", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-managed-service-identity", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "5ac94222-3e13-4810-9230-81a941741583", + "id": "C03.05", "services": [ - "ServiceBus", - "AppSvc", - "VM", - "Storage", - "Entra", - "AKV" + "AVS" ], - "severity": "Medium", - "subcategory": "Identity and Access Management", - "text": "When possible, your application should be using a managed identity to authenticate to Azure Service Bus. If not, consider having the storage credential (SAS, service principal credential) in Azure Key Vault or an equivalent service", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "severity": "High", + "subcategory": "Security (guest/VM)", + "text": "Ensure extended security update support is configured for workloads running on Azure VMware Solution (Azure VMware Solution is eligible for ESU)", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "When creating permissions, provide fine-grained control over a client's access to Azure Service Bus. Permissions in Azure Service Bus can and should be scoped to the individual resource level e.g. queue, topic or subscription. ", - "guid": "f615658d-e558-4f93-9249-b831112dbd7e", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/authenticate-application#azure-built-in-roles-for-azure-service-bus", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "3ef7ad7c-6d37-4331-95c7-acbe44bbe609", + "id": "C04.01", "services": [ - "ServiceBus", - "RBAC", "Storage", - "Entra", - "Subscriptions" + "VM", + "AVS", + "AzurePolicy" ], "severity": "High", - "subcategory": "Identity and Access Management", - "text": "Use least privilege data plane RBAC", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" + "subcategory": "Governance (platform)", + "text": "Ensure that the appropriate VM template storage policy is used", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "Azure Service Bus resource logs include operational logs, virtual network and IP filtering logs. Runtime audit logs capture aggregated diagnostic information for various data plane access operations (such as send or receive messages) in Service Bus.", - "guid": "af12e7f9-43f6-4304-922d-929c2b1cd622", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/monitor-service-bus-reference", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "d89f2e87-7784-424d-9167-85c6fa95b96a", + "id": "C04.02", "services": [ - "ServiceBus", - "VNet", - "Monitor" + "AVS", + "ASR" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable logging for security investigation. Use Azure Monitor to trace resource logs and runtime audit logs (currently available only in the premium tier)", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" + "severity": "Low", + "subcategory": "Governance (platform)", + "text": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "Azure Service Bus by default has a public IP address and is Internet-reachable. Private endpoints allow traffic between your virtual network and Azure Service Bus traverses over the Microsoft backbone network. In addition to that, you should disable public endpoints if those are not used. ", - "guid": "9ae669ca-48e4-4a85-b222-3ece8bb12307", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/private-link-service", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "d88408f3-7273-44c8-96ba-280214590146", + "id": "C04.03", "services": [ - "ServiceBus", - "VNet", - "PrivateLink" + "Storage", + "AVS", + "AzurePolicy" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Consider using private endpoints to access Azure Service Bus and disable public network access when applicable.", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "severity": "High", + "subcategory": "Governance (platform)", + "text": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Service Bus Review", - "description": "With IP firewall, you can restrict the public endpoint further to only a set of IPv4 addresses or IPv4 address ranges in CIDR (Classless Inter-Domain Routing) notation. ", - "guid": "ca5f06f1-58e3-4ea3-a92c-2de7e2165c3a", - "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-ip-filtering", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "5d38e53f-9ccb-4d86-a266-acca274faa19", + "id": "C04.04", "services": [ - "ServiceBus" + "AVS" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Consider only allowing access to Azure Service Bus namespace from specific IP addresses or ranges", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "subcategory": "Governance (platform)", + "text": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions.", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD control plane does not offer a financially backed service level agreement. We strive to attain at least 99.9% availability for the Azure Virtual Desktop service URLs. The availability of the session host virtual machines in your subscription is covered by the Virtual Machines SLA. Dependent resources/services and infrastructure availability must be also considered to properly satisfy global high-availability requirements.", - "guid": "56c57ba5-9119-4bf8-b8f5-c586c7d9cdc1", - "id": "A01.01", - "link": "https://azure.microsoft.com/support/legal/sla/virtual-desktop/v1_0/", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "bf39d95d-44c7-4c89-89ca-1f6d5315ae52", + "id": "C04.05", "services": [ - "VM", - "Subscriptions", - "AVD", - "ASR" + "AVS", + "AzurePolicy" ], - "severity": "High", - "subcategory": "Compute", - "text": "Determine the expected High Availability SLA for applications/desktops published through AVD", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Governance (platform)", + "text": "Ensure that you have a policy around ESXi host density and efficiency, keeping in mind the lead time for requesting new nodes", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "'Active-Active' model can be achieved with multiple host pools in different regions. A single Host Pool with VMs from different regions is not recommended. If multiple pools for same users will be used, the problem of how to synchronize/replicate user profiles must be solved. FSLogix Cloud Cache could be used, but need to be carefully reviewed and planned, or customers can decide to do not synchronize/replicate at all. 'Active-Passive' can be achieved using Azure Site Recovery (ASR) or on-demand Pool deployment with automated mechanism. For a detailed discussion on multi-region BCDR, please read the companion article in the 'More Info' column and this FSLogix related page: https://learn.microsoft.com/fslogix/concepts-container-recovery-business-continuity.", - "guid": "6acc076e-f9b1-441a-a989-579e76b897e7", - "id": "A01.02", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/azure-virtual-desktop-multi-region-bcdr", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "4ba34d45-85e1-4213-abd7-bb012f7b95ef", + "id": "C04.06", "services": [ - "VM", - "AVD", - "Storage", - "ASR" + "AVS", + "Cost" ], "severity": "Medium", - "subcategory": "Compute", - "text": "Assess Geo Disaster Recovery requirements for AVD Host Pools", - "waf": "Reliability" + "subcategory": "Governance (platform)", + "text": "Ensure a good cost management process is in place for Azure VMware Solution - Azure Cost Management can be used", + "waf": "Cost" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Before approaching Azure Virtual Desktop BCDR planning and design, it is important to initially consider which applications consumed through AVD are critical. You may want to separate them from non-critical apps and use a separate Host Pool with a different disaster recovery approach and capabilities.", - "guid": "10a7da7b-e996-46e1-9d3c-4ada97cc3d13", - "id": "A01.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "6e043e2a-a359-4271-ae6e-205172676ae4", + "id": "C04.07", "services": [ - "AVD", - "ASR" + "AVS", + "Cost" ], "severity": "Low", - "subcategory": "Compute", - "text": "Separate critical applications in different AVD Host Pools", - "waf": "Reliability" + "subcategory": "Governance (platform)", + "text": "Are Azure reserved instances used to optimize cost for using Azure VMware Solution", + "waf": "Cost" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Each Host Pool can be deployed using Availability Zones (AZ) or Availability Set (AS). To maximize resiliency, usage of AZ is recommended: at Host Pool creation time you can decide to spread Host Pool Session Hosts across all available AZ. Usage of AS will not protect from single datacenter failure, then should be used only in regions where AZ are not available. More details on AZ and AVD in the companion article. For a comparison between AZ and AS you can read here: https://learn.microsoft.com/azure/virtual-machines/availability.", - "guid": "25ab225c-6f4e-4168-9fdd-dea8a4b7cdeb", - "id": "A01.04", - "link": "https://techcommunity.microsoft.com/t5/azure-virtual-desktop-blog/announcing-general-availability-of-support-for-azure/ba-p/3636262", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "6691e883-5ac9-4422-83e1-3810523081a9", + "id": "C04.08", "services": [ - "AVD", - "ACR", - "ASR" + "AVS" ], - "severity": "High", - "subcategory": "Compute", - "text": "Plan the best resiliency option for AVD Host Pool deployment", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Governance (platform)", + "text": "Consider the use of Azure Private-Link when using other Azure Native Services", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Backup can be used to protect Host Pool VMs. For Pooled Pools, this is not necessary since should be stateless. Instead, this option can be considered for Personal Host Pools.", - "guid": "4c61fc3f-c14e-4ea6-b69e-8d9a3eec218e", - "id": "A01.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "48b262d6-cc5f-4512-a253-98e6db9d37da", + "id": "C05.01", "services": [ + "Defender", "VM", - "Backup", - "AVD", - "ASR" + "AVS" ], "severity": "Medium", - "subcategory": "Compute", - "text": "Assess the requirement to backup AVD Session Host VMs", - "waf": "Reliability" + "subcategory": "Governance (guest/VM)", + "text": "Enable Microsoft Defender for Cloud for Azure VMware Solution guest VM workloads", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Even for Personal Pools, usage of Availability Zones, when available, is recommended. Three possible in-region DR strategies are possible, it is recommended to select the best one based on cost, RTO/RPO, and if it is really necessary to save the entire VM OS disk: (1) create each session host in a specific zone (AZ) and then use Azure Site Recovery (ASR) to replicate to a different zone. (2) Use Azure Backup to backup and restore the specific session host in a different AZ. (3) Create a new session host in a different AZ and rely on FSLogix and/or OneDrive to make data and settings available on the new machine. All options require administrator intervention for DR and direct user assignment at Host Pool level, then must be planned and configured in advance.", - "guid": "5da58639-ca3a-4961-890b-29663c5e10d", - "id": "A01.06", - "link": "https://learn.microsoft.com/azure/site-recovery/azure-to-azure-how-to-enable-zone-to-zone-disaster-recovery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "41741583-3ef7-4ad7-a6d3-733165c7acbe", + "id": "C05.02", "services": [ "VM", - "Cost", - "Backup", - "AVD", - "ASR" + "AVS", + "Arc" ], "severity": "Medium", - "subcategory": "Compute", - "text": "Prepare a local DR strategy for Personal Host Pool Session Hosts", - "waf": "Reliability" + "subcategory": "Governance (guest/VM)", + "text": "Use Azure Arc enabled servers to manage your Azure VMware Solution guest VM workloads", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "If custom images are used to deploy AVD Host Pool VMs, it is important to ensure those artifacts are available in all regions where AVD is deployed. Azure Compute Gallery service can be used to replicate images across all regions where a Host Pool is deployed, with redundant storage and in multiple copies. Please be aware that the Azure Compute Gallery service isn't a global resource. For disaster recovery scenarios, the best practice is to have at least two galleries, in different regions.", - "guid": "dd2e0d5d-771d-441e-9610-cc57b4a4a141", - "id": "A02.01", - "link": "https://learn.microsoft.com/azure/virtual-machines/azure-compute-gallery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "88f03a4d-2cd4-463c-abbc-868295abc91a", + "id": "C05.03", "services": [ - "VM", - "Storage", - "AVD", - "ASR", - "ACR" + "AVS" ], - "severity": "Low", - "subcategory": "Dependencies", - "text": "Plan for Golden Image cross-region availability", - "waf": "Reliability" + "severity": "High", + "subcategory": "Governance (guest/VM)", + "text": "Enable Diagnostic and metric logging on Azure VMware Solution", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "If users of the AVD infrastructure need on-premises resource access, high availability of network infrastructure required to connect is also critical and should be considered. Resiliency of authentication infrastructure needs to be assessed and evaluated. BCDR aspects for dependent applications and other resources need to be considered to ensure availability in the secondary DR location.", - "guid": "fd339489-8c12-488b-9c6a-57cfb644451e", - "id": "A02.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "4ed90dae-2cc8-44c4-9b6b-781cbafe6c46", + "id": "C05.04", "services": [ - "AVD", - "ASR" + "Monitor", + "VM", + "AVS" ], "severity": "Medium", - "subcategory": "Dependencies", - "text": "Assess Infrastructure & Application dependencies ", - "waf": "Reliability" + "subcategory": "Governance (guest/VM)", + "text": "Deploy the Log Analytics Agents to Azure VMware Solution guest VM workloads", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Not all data inside FSLogix user profiles may deserve protection from disaster. Additionally, if external storage is used, for example OneDrive or File Servers/Shares, what is remaining in the FSLogix profile is minimal and could be lost in some extreme circumstances. In other cases, data inside the profile can be rebuilt from other storages (for example Outlook Inbox in cached mode).", - "guid": "687ab077-adb5-49e5-a960-3334fdf8cc23", - "id": "A03.01", - "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "589d457a-927c-4397-9d11-02cad6aae11e", + "id": "C05.05", "services": [ - "AVD", - "Storage", - "ASR" + "VM", + "AVS", + "Backup", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Assess which data need to be protected in the Profile and Office Containers", - "waf": "Reliability" + "subcategory": "Governance (guest/VM)", + "text": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Preventing data loss for critical user data is important, first step is to assess which data need to be saved and protected. If using OneDrive or other external storage, saving user Profile and/or Office Containers data maybe not necessary. Appropriate mechanism must be considered to provide protection for critical user data. Azure Backup service can be used to protect Profile and Office Containers data when stored on Azure Files Standard and Premium tiers. Azure NetApp Files Snapshots and Policies can be used for Azure NetApp Files (all tiers).", - "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", - "id": "A03.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "ee29711b-d352-4caa-ab79-b198dab81932", + "id": "C06.01", "services": [ - "Storage", - "Backup", - "AVD", - "ASR", - "AzurePolicy" + "Defender", + "AVS", + "Monitor" + ], + "severity": "Medium", + "subcategory": "Compliance", + "text": "Use Microsoft Defender for Cloud for compliance monitoring of workloads running on Azure VMware Solution", + "waf": "Security" + }, + { + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "c9fc9d1b-b780-436f-9e6b-fbb9ed503547", + "id": "C06.02", + "services": [ + "Defender", + "AVS" ], "severity": "Medium", - "subcategory": "Storage", - "text": "Build a backup protection strategy for Profile and Office Containers", - "waf": "Reliability" + "subcategory": "Compliance", + "text": "Are the applicable compliance baselines added to Microsoft Defender for Cloud", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "In AVD, multiple replication mechanisms and strategies can be used for user data residing in FSLogix containers: [Profile Pattern #1]: Native Azure storage replication mechanisms, for example Azure Files Standard GRS replication, Azure NetApp Files Cross Region Replication. Use Zone Replicated Storage (ZRS) or Geo replicated storage (GRS) for Azure Files is recommended. LRS with local-only resiliency can be used if no zone/region protection is required. NOTE: Azure Files Share Standard is LRS/ZRS/GRS, but with 100TB large support enabled only LRS/ZRS are supported. [Profile Pattern #2]: FSLogix Cloud Cache is built in automatic mechanism to replicate containers between different (up to 4) storage accounts. Cloud Cache should be used only when:(1) User Profile or Office containers data availability required high-availability SLA is critical and need to be resilient to region failure. (2) Selected storage option is not able to satisfy BCDR requirements. For example, with Azure File Share Premium tier, or Azure File Share Standard with Large File Support enabled, GRS is not available. (3) When replication between disparate storage is required. [Profile Pattern #3]: Only set up geo disaster recovery for application data and not for user data/profile containers: store important application data in separate storages, like OneDrive or other external storage with its own built-in DR mechanism.", - "guid": "9f7547c1-746d-4c56-868a-714435bd09dd", - "id": "A03.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "cc447e82-6128-4a71-b0f1-cac6d9ef1d5e", + "id": "C06.03", "services": [ - "AVD", - "Storage", - "ASR" + "AVS" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Assess Profile Container storage replication requirements and resiliency for BCDR purpose", - "waf": "Reliability" + "severity": "High", + "subcategory": "Compliance", + "text": "Was data residency evaluated when selecting Azure regions to use for Azure VMware Solution deployment", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "For local disaster recovery, Azure Backup for Azure Files can be used. For cross-region geo disaster recovery: GRS for Azure Files is only available with standard SKU and no large share support, then not suitable in most customer scenarios. If geo-replication is required with Azure File Share Premium, replication with FSLogix Cloud Cache can be evaluated, or 'in-region' Availability Zone (AZ) only resiliency should be considered.", - "guid": "3d4f3537-c134-46dc-9602-7a71efe1bd05", - "id": "A03.04", - "link": "https://docs.microsoft.com/azure/backup/backup-afs", + "category": "Governance", + "checklist": "Azure VMware Solution Design Review", + "guid": "832e42e3-611c-4818-a0a0-bc510e43a18a", + "id": "C06.04", "services": [ - "Backup", - "AVD", - "Storage", - "ASR" + "AVS" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Review Azure Files disaster recovery strategy", - "waf": "Reliability" + "severity": "High", + "subcategory": "Compliance", + "text": "Are data processing implications (service provider / service consumer model) clear and documented", + "waf": "Security" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "Zone Redundant Storage will maximize in-region resiliency for the user profile data. ZRS is supported for premium file shares through the 'FileStorage' storage account kind. ZRS is supported in standard general-purpose v2 storage accounts. Usage of zone redundant storage must be paired with zone redundant deployment of Session Hosts in each Host Pool. ", - "guid": "10d4e875-d502-4142-a795-f2b6eff34f88", - "id": "A03.05", - "link": "https://learn.microsoft.com/azure/storage/files/files-redundancy#zone-redundant-storage", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "e43a18a9-cd28-49ce-b6b1-7db8255461e2", + "id": "D01.01", "services": [ - "AVD", - "Storage", - "ASR" + "Monitor", + "AVS" ], "severity": "High", - "subcategory": "Storage", - "text": "Use Zone Redundant Storage (ZRS) for Azure Files to maximize resiliency", - "waf": "Reliability" + "subcategory": "Monitoring", + "text": "Create dashboards to enable core Azure VMware Solution monitoring insights", + "waf": "Operations" }, { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Virtual Desktop Review", - "description": "For local disaster recovery, Azure NetApp Files (ANF) native backup is available. ANF is essentially locally redundant, then for cross-region geo disaster recovery it is necessary to use an additional mechanism that is Cross-Region Replication (CRR) https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering. Currently, ANF does not provide replication nor redundancy across different Availability Zones (AZ), only the possibility to select in which single AZ to place the ANF volume: https://learn.microsoft.com/azure/azure-netapp-files/manage-availability-zone-volume-placement.", - "guid": "23429db7-2281-4376-85cc-57b4a4b18142", - "id": "A03.06", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "6b84ee5d-f47d-42d9-8881-b1cd5d1e54a2", + "id": "D01.02", "services": [ - "Storage", - "Backup", - "AVD", - "ASR", - "ACR" + "Monitor", + "AVS" ], - "severity": "Medium", - "subcategory": "Storage", - "text": "Review Azure NetApp Files disaster recovery strategy", - "waf": "Reliability" + "severity": "High", + "subcategory": "Monitoring", + "text": "Create warning alerts for critical thresholds for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Applications can be preinstalled in the golden image/s, can be attached using MSIX & AppAttach feature or distributed to the session hosts after host pool deployment using traditional software distribution methods.", - "guid": "86ba2802-1459-4014-95d3-8e5309ccbd97", - "id": "B01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "9659e396-80e7-4828-ac93-5657d02bff45", + "id": "D01.03", "services": [ - "AVD" + "Monitor", + "AVS" ], "severity": "High", - "subcategory": "Golden Images", - "text": "Determine how applications will be deployed in AVD Host Pools", + "subcategory": "Monitoring", + "text": "Ensure critical alert is created to monitor if vSAN consumption is below 75% as this is a support threshold from VMware", "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Multiple golden images can be required to support different OS versions and/or settings, different groups of applications that must be separated and cannot be included in a single image.", - "guid": "9266bcca-274f-4aa1-abf3-9d95d44c7c89", - "id": "B01.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "64b0d934-a348-4726-be79-d6b5c3a36495", + "id": "D01.04", "services": [ - "AVD" + "Monitor", + "AVS" ], - "severity": "Medium", - "subcategory": "Golden Images", - "text": "Estimate the number of golden images that will be required", + "severity": "High", + "subcategory": "Monitoring", + "text": "Ensure alerts are configured for Azure Service Health alerts and notifications", "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Determine which Guest OS will be used to deploy each Host Pool: Windows 10 vs. Windows Server, Marketplace vs. Custom images", - "guid": "19ca1f6d-5315-4ae5-84ba-34d4585e2213", - "id": "B01.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#operating-systems-and-licenses", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "b6abad38-aad5-43cc-99e1-d86667357c54", + "id": "D01.05", "services": [ - "AVD" + "Storage", + "AVS", + "Monitor" ], "severity": "Medium", - "subcategory": "Golden Images", - "text": "Determine which OS image/s you will use for Host Pool deployment", - "waf": "Reliability" + "subcategory": "Monitoring", + "text": "Configure Azure VMware Solution logging to be send to an Azure Storage account or Azure EventHub for processing", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure VM custom images can be created and stored in different ways: in an Azure Compute Gallery, as a managed image object or as a managed disk in the storage. The recommended way is to use Azure Compute Gallery.", - "guid": "5a2adb2c-3e23-426b-b225-ca44e1696fdd", - "id": "B01.04", - "link": "https://learn.microsoft.com/azure/virtual-machines/shared-image-galleries", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "9674c5ed-85b8-459c-9733-be2b1a27b775", + "id": "D01.06", "services": [ - "VM", - "AVD", - "Storage" + "Monitor", + "AVS" ], "severity": "Low", - "subcategory": "Golden Images", - "text": "Select the proper store for custom images", - "waf": "Reliability" + "subcategory": "Monitoring", + "text": "If deep insight in VMware vSphere is required: Is vRealize Operations and/or vRealize Network Insights used in the solution?", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "If custom images will be used, plan for an automated build process. If no pre-existing software factory exists, consider using Custom Image Templates and/or Azure Image Builder to automate the build process.", - "guid": "9bd7bb01-2f7b-495e-86e1-54e2aa359282", - "id": "B01.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-custom-image-templates", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "a91be1f3-88f0-43a4-b2cd-463cbbbc8682", + "id": "D02.01", "services": [ - "AVD" + "Storage", + "VM", + "AVS", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Design your build process for custom images", + "severity": "High", + "subcategory": "Operations", + "text": "Ensure the vSAN storage policy for VM's is NOT the default storage policy as this policy applies thick provisioning", "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "There are some known best practices and recommendations for the golden image customization, be sure to check the referenced article.", - "guid": "deace4cb-1dec-44c6-90c3-fc14eebb36a3", - "id": "B01.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "d9ef1d5e-832d-442e-9611-c818b0afbc51", + "id": "D02.02", "services": [ - "AVD" + "AVS" ], "severity": "Medium", - "subcategory": "Golden Images", - "text": "If custom image will be used, check recommended best practices for AVD on how to build custom image", + "subcategory": "Operations", + "text": "Ensure vSphere content libraries are not placed on vSAN as vSAN is a finite resource", "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "FSLogix stack installed in AVD session hosts does not provide auto-update capability. For this reason, it is recommended to download the latest version of FSLogix and include in the golden image update process.", - "guid": "ed5c9027-dd1a-4343-86ca-52b199223186", - "id": "B01.07", - "link": "https://learn.microsoft.com/fslogix/how-to-install-fslogix", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "0e43a18a-9cd2-489b-bd6b-17db8255461e", + "id": "D02.03", "services": [ - "AVD" + "Storage", + "AVS", + "Backup" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Ensure data repositories for the backup solution are stored outside of vSAN storage. Either in Azure native or on a disk pool-backed datastore", + "waf": "Operations" + }, + { + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "2aee3453-aec8-4339-848b-262d6cc5f512", + "id": "D02.04", + "services": [ + "AVS", + "Arc" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Ensure workloads running on Azure VMware Solution are hybrid managed using Azure Arc for Servers (Arc for Azure VMware Solution is in preview)", + "waf": "Operations" + }, + { + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "925398e6-da9d-437d-ac43-bc6cd1d79a9b", + "id": "D02.05", + "services": [ + "Monitor", + "AVS" ], - "severity": "High", - "subcategory": "Golden Images", - "text": "Include the latest version of FSLogix in the golden image update process", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Operations", + "text": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "This tool-set has been created to automatically apply setting referenced in white paper 'Optimizing Windows 10, version 2004 for a Virtual Desktop Infrastructure (VDI) role': https://docs.microsoft.com/windows-server/remote/remote-desktop-services/rds-vdi-recommendations-2004. Usage of the tool and/or optimizations mentioned in the white-paper should be considered. ", - "guid": "829e3fec-2183-4687-a017-7a2b5945bda4", - "id": "B01.08", - "link": "https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "24604489-a8f4-42d7-ae78-cb6a33bd2a09", + "id": "D02.06", "services": [ - "AVD", - "RBAC" + "AVS" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Evaluate the usage of Virtual-Desktop-Optimization-Tool", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Operations", + "text": "Include workloads running on Azure VMware Solution in existing update management tooling or in Azure Update Management", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "If OneDrive is used and included in a golden image, be sure to follow the configuration procedure reported in the companion article in the 'More Info' section. Not in scope in this AVD checklist, but OneDrive optimizations like 'Known Folder Redirection' and 'Files On-Demand' should be evaluated used to reduce the space used in FSLogix profiles and provide a better user experience. OneDrive today is not supported for Remote Apps.", - "guid": "e3d3e084-4276-4d4b-bc01-5bcf219e4a1e", - "id": "B01.09", - "link": "https://learn.microsoft.com/azure/virtual-desktop/install-office-on-wvd-master-image#install-onedrive-in-per-machine-mode", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "17e7a8d9-0ae0-4e27-aee2-9711bd352caa", + "id": "D02.07", "services": [ - "AVD", - "Storage" + "Monitor", + "AVS", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Determine if Microsoft OneDrive will be part of AVD deployment", + "severity": "Medium", + "subcategory": "Operations", + "text": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions", "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Be sure to review the requirements and configuration procedure contained in the companion article in the 'More Info' column. Since Teams automatic updates will be disabled, it is recommended to check and include Teams latest version in the golden image update process.", - "guid": "b5887953-5d22-4788-9d30-b66c67be5951", - "id": "B01.10", - "link": "https://learn.microsoft.com/azure/virtual-desktop/teams-on-AVD", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "ab79b188-dab8-4193-8c9f-c9d1bb77036f", + "id": "D02.08", "services": [ - "AVD" + "Storage", + "VM", + "AVS" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Determine if Microsoft Teams will be part of AVD deployment", - "waf": "Performance" + "severity": "High", + "subcategory": "Operations", + "text": "When ANF is used to extend storage for Azure VMware Solution, ensure it is used at the VM level only for now (ANF as NFS datastore is still in private preview)", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD can support users with different language and localization requirements in the same host pool. This can be done customizing golden images to ensure users can select whichever language they need. The procedure to configure additional language packs in Windows 11 is documented in the reference article.", - "guid": "7c336f3b-822a-498e-8cd1-667d1150df4a", - "id": "B01.11", - "link": "https://learn.microsoft.com/azure/virtual-desktop/windows-11-language-packs", + "category": "Management", + "checklist": "Azure VMware Solution Design Review", + "guid": "aee3553a-fc83-4392-98b2-62d6cc5f5129", + "id": "D03.01", "services": [ - "AVD" + "Defender", + "AVS" ], - "severity": "Low", - "subcategory": "Golden Images", - "text": "Assess the requirement to support multiple languages", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Security", + "text": "Ensure workloads running on Azure VMware Solution are onboarded to Microsoft Defender for Cloud", + "waf": "Security" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "It is highly recommended to use separate storage accounts/shares to store MSIX packages. If necessary, storage can scale out independently and not being impacted by profile I/O activities. Azure offers multiple storage options that can be used for MISX app attach. We recommend using Azure Files or Azure NetApp Files as those options offer the best value between cost and management overhead. ", - "guid": "90083845-c587-4cb3-a1ec-16a1d076ef9f", - "id": "B02.01", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "25398e6d-b9d3-47da-a43b-c6cd1d79a9b2", + "id": "E01.01", "services": [ - "AVD", - "Storage", - "Cost" + "AVS", + "Backup" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Do not use the same storage account/share as FSLogix profiles", - "waf": "Performance" + "subcategory": "Backup", + "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource", + "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "In the referenced article, we reported few but important performance considerations for MSIX usage in AVD context, be sure to carefully review.", - "guid": "241addce-5793-477b-adb3-751ab2ac1fad", - "id": "B02.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "5e6bfbb9-ed50-4354-9cc4-47e826028a71", + "id": "E02.01", "services": [ - "AVD" + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Review performance considerations for MSIX", - "waf": "Performance" + "subcategory": "Disaster Recovery", + "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution", + "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "MSIX app attach requires read-only permissions to access the file share. If you're storing your MSIX applications in Azure Files, then for your session hosts, you'll need to assign all session host VMs both storage account role-based access control (RBAC) and file share New Technology File System (NTFS) permissions on the share.", - "guid": "66e15d4d-5a2a-4db2-a3e2-326bf225ca41", - "id": "B02.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "f0f1cac6-d9ef-41d5-b832-d42e3611c818", + "id": "E02.02", "services": [ - "VM", - "AVD", - "RBAC", - "Storage" + "AVS", + "ASR" ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Check proper session host permissions for MSIX share", - "waf": "Security" + "subcategory": "Disaster Recovery", + "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS", + "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "3rd-party software vendor must provide a MSIX package, it is not recommended for customer to attempt the conversion procedure without proper support from the application owner.", - "guid": "bd362caa-ab79-4b19-adab-81932c9fc9d1", - "id": "B02.04", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "b0afbc51-0e43-4a18-a9cd-289bed6b17db", + "id": "E02.03", "services": [ - "AVD" + "AVS", + "ASR" ], - "severity": "Low", - "subcategory": "MSIX & AppAttach", - "text": "MSIX packages for 3rd-party applications", - "waf": "Cost" + "severity": "High", + "subcategory": "Disaster Recovery", + "text": "Use Automated recovery plans with either of the Disaster solutions, avoid manual tasks as much as possible", + "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "MSIX app attach doesn't support auto-update for MSIX applications, so they should be disabled.", - "guid": "bb88037f-5e6b-4fbb-aed5-03547cc447e8", - "id": "B02.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "8255461e-2aee-4345-9aec-8339248b262d", + "id": "E02.04", "services": [ - "AVD" + "AVS", + "ASR" ], - "severity": "Low", - "subcategory": "MSIX & AppAttach", - "text": "Disable auto-update for MSIX packages", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use the geopolitical region pair as the secondary disaster recovery environment", + "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "In order to leverage MSIX & App Attach, guest OS image for AVD Host pool must be Windows 10/11 Enterprise or Windows 10/11 Enterprise Multi-session, version 2004 or later.", - "guid": "26128a71-f0f1-4cac-9d9e-f1d5e832e42e", - "id": "B02.06", - "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "6cc5f512-9253-498e-9da9-d37dac43bc6c", + "id": "E02.05", "services": [ - "AVD" + "AVS", + "ASR" ], - "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Review operating systems support", + "severity": "High", + "subcategory": "Disaster Recovery", + "text": "Use 2 different address spaces between the regions, for example: 10.0.0.0/16 and 192.168.0.0/16 for the different regions", "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Once selected the VM SKU that will be used for Host Pool deployment, it is recommended to use Gen2 type of the SKU for higher security and improved capabilities.", - "guid": "e4633254-3185-40a1-b120-bd563a1c8e9d", - "id": "B03.01", - "link": "https://docs.microsoft.com/azure/virtual-machines/generation-2", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "d1d79a9b-2460-4448-aa8f-42d78e78cb6a", + "id": "E02.06", "services": [ - "VM", - "AVD" + "ExpressRoute", + "AVS", + "NVA", + "ASR" ], "severity": "Medium", - "subcategory": "Session Host", - "text": "Evaluate the usage of Gen2 VM for Host Pool deployment", - "waf": "Performance" + "subcategory": "Disaster Recovery", + "text": "Will ExpressRoute Global Reach be used for connectivity between the primary and secondary Azure VMware Solution Private Clouds or is routing done through network virtual appliances?", + "waf": "Reliability" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "MMR redirects the media content from Session Host to your local machine for faster processing and rendering. It only works when you play media content on Microsoft Edge or Google Chrome. See linked URL for more details.", - "guid": "adecb27f-dc40-40f5-aca2-0090f633b1c9", - "id": "B03.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/multimedia-redirection", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "33bd2a09-17e7-4a8d-a0ae-0e27cee29711", + "id": "E03.01", "services": [ - "AVD" - ], - "severity": "Low", - "subcategory": "Session Host", - "text": "Consider using MMR (MultiMedia Redirection) to get better video performance on browser", - "waf": "Performance" + "AVS", + "Backup" + ], + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Use MABS as your backup solution", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "A host pool is a collection of Azure virtual machines that register to Azure Virtual Desktop as session hosts. A host pool can be one of two types: Personal and Pooled. Which type to use, and how many, is a key design decision that must be documented and validated. See companion article in 'More Info' column for more details.", - "guid": "8468c55a-775c-46ee-a5b8-6ad8844ce3b2", - "id": "C01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology#host-pools", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "bd352caa-ab79-4b18-adab-81932c9fc9d1", + "id": "E03.02", "services": [ - "VM", - "AVD" + "AVS", + "Backup" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Determine the Host Pool type to use", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Use your design criteria to determine the number of Host Pools to deploy. This will be based on factors such as different OS images, multi-region support, guest VM hardware differences (such as GPU support or no), different user expectations and uptime requirements (examples might be 'Executives', 'Office Workers', 'Developers', etc.), and Host Pool RDP settings (such as drive redirection support). These will determine the number of host pools as well as how many hosts will be in each pool.", - "guid": "4e98495f-d3c0-4af2-aa59-a793395a32a7", - "id": "C01.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#host-pools", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "bb77036f-5e6b-4fbb-aed5-03547cc447e8", + "id": "E03.03", "services": [ - "VM", - "AVD" + "AVS" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Estimate the number of different Host Pools to deploy ", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Confirm that the difference between automatic and direct assignment is well understood and the selected option is appropriate for the scenario in question. Automatic is the default setting.", - "guid": "b38b875b-a1cf-4204-a901-3a5d3ce474db", - "id": "C01.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type", + "category": "BCDR", + "checklist": "Azure VMware Solution Design Review", + "guid": "26028a71-f0f1-4cac-9d9e-f1d5e832d42e", + "id": "E03.04", "services": [ - "AVD" + "AVS" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "For Personal Host Pool type, select the proper assignment type", - "waf": "Operations" + "subcategory": "Business Continuity", + "text": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Check which one to use and available options, autoscale ignores existing load-balancing algorithms.", - "guid": "cbd8682a-6abc-4a2a-9fda-1dbf3dc95d48", - "id": "C01.04", - "link": "https://docs.microsoft.com/azure/virtual-desktop/host-pool-load-balancing", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "4604489a-8f42-4d78-b78c-b7a33bd2a0a1", + "id": "F01.01", "services": [ - "AVD" + "AVS" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "For Pooled Host Pool type, select the best load balancing method", - "waf": "Performance" + "subcategory": "Deployment strategy", + "text": "For manual deployments, all configuration and deployments must be documented", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "The number of cores increase, the system's synchronization overhead also increases. Especially for multiple user's sign-in simultaneously. Make sure not to use a VM that is too large for the session host", - "guid": "b3724959-4943-4577-a3a9-e10ff6345f24", - "id": "C01.05", - "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "7e7a8d90-ae0e-437c-be29-711bd352caaa", + "id": "F01.02", "services": [ - "VM", - "AVD" + "AVS" ], - "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "For Pooled Host Pool type, VMs shouldn't have more than 32 cores", - "waf": "Performance" + "severity": "Low", + "subcategory": "Deployment strategy", + "text": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD does not support assigning both the RemoteApp and Desktop Application Group (DAG) in a single host pool to the same set of users. Doing so will cause a single user to have two user sessions in a single host pool. Users aren't supposed to have two active sessions at the same time in the same host pool using the same profile.", - "guid": "b384b7ed-1cdd-457e-a2cd-c8d4d55bc144", - "id": "C01.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#application-groups", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "b79b198d-ab81-4932-a9fc-9d1bb78036f5", + "id": "F02.01", "services": [ - "AVD", - "Storage" + "AVS" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Do not use the same Host Pool to offer both full desktops (DAG) and Remote Apps to the same set of users", - "waf": "Security" + "severity": "Low", + "subcategory": "Automated Deployment", + "text": "For automated deployments, deploy a minimal private cloud and scale as needed", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "There is a limit of 500 Application Groups that can be created in AVD for each Microsoft Entra ID (former Azure AD) tenant. The limit can be increased (see the companion link for details) but it is not recommended.", - "guid": "971cc4a4-b1f7-4c12-90e0-1ad96808f00c", - "id": "C01.07", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-virtual-desktop-service-limits", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "e6bfbb9e-d503-4547-ac44-7e826128a71f", + "id": "F02.02", "services": [ - "AVD", - "ACR", - "Entra" + "AVS" ], - "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Estimate the number of Application Groups required across all Host Pools in the Microsoft Entra ID tenant", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Automated Deployment", + "text": "For automated deployments, request or reserve quota prior to starting the deployment", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Applications are grouped under Application Groups as containers for publishing and assigning permissions: we recommend that you do not publish more than 50 applications per application group.", - "guid": "fa9f2895-473d-439b-ab8e-5a5cf92c7f32", - "id": "C01.08", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "0f1cac6d-9ef1-4d5e-a32e-42e3611c818b", + "id": "F02.03", "services": [ - "AVD" + "AVS", + "AzurePolicy" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Estimate the number of Applications for each Application Group", - "waf": "Reliability" + "subcategory": "Automated Deployment", + "text": "For automated deployment, ensure that relevant resource locks are created through the automation or through Azure Policy for proper governance", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "FSLogix is not required for Personal Host Pools since each VM is statically assigned to a single user, then no immediate needs for a roaming profile solution. In some usage scenarios FSLogix can help. For example, a VM can be re-assigned, or user moved to another desktop, or roaming profile can be used to save user profile in a different location for DR purposes.", - "guid": "38b19ab6-0693-4992-9394-5590883916ec", - "id": "C01.09", - "link": "https://learn.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type?tabs=azure#reassign-a-personal-desktop", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "e2cc95d4-8c6b-4791-bca0-f6c56589e558", + "id": "F03.01", "services": [ - "VM", - "AVD", - "Storage" + "AKV", + "AVS" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Evaluate the usage of FSLogix for Personal Host Pools", - "waf": "Reliability" + "subcategory": "Automated Connectivity", + "text": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Use the link provided to set a starting point for SKU decision, then validate using a performance test. Ensure a minimum of four cores for Production is selected per Session Host (multi-session)", - "guid": "e1112dbd-7ba0-412e-9b94-ef6e047d2ea2", - "id": "C01.10", - "link": "https://docs.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "255461e2-aee3-4553-afc8-339248b262d6", + "id": "F03.02", "services": [ - "VM", - "AVD" + "ExpressRoute", + "AKV", + "AVS" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Run workload performance test to determine the best Azure VM SKU and size to use", - "waf": "Performance" + "severity": "Low", + "subcategory": "Automated Connectivity", + "text": "Use Key vault to store secrets and authorization keys when separate Service Principles are used for deploying Azure VMware Solution and ExpressRoute", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "It is critical to check AVD capacity and limits reported in the referenced article. Additional limits and thresholds apply for network, compute, storage and service management. ", - "guid": "992b1cd6-d2f5-44b2-a769-e3a691e8838a", - "id": "C01.11", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "cc5f5129-2539-48e6-bb9d-37dac43bc6cd", + "id": "F03.03", "services": [ - "AVD", - "Storage" + "AVS" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Verify AVD scalability limits for the environment", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Automated Connectivity", + "text": "Define resource dependencies for serializing actions in IaC when many resources need to be deployed in/on Azure VMware Solution as Azure VMware Solution only supports a limited number of parallel operations.", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Host Pools with GPU require special configuration, please be sure to review the referenced article.", - "guid": "c936667e-13c0-4056-94b1-e945a459837e", - "id": "C01.12", - "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-vm-gpu", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "1d79a9b2-4604-4489-a8f4-2d78e78cb7a3", + "id": "F03.04", "services": [ - "AVD" + "AVS" ], "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Determine if Session Hosts will require GPU", - "waf": "Performance" + "subcategory": "Automated Connectivity", + "text": "When performing automated configuration of NSX-T segments with a single Tier-1 gateway, use Azure Portal APIs instead of NSX-Manager APIs", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Whenever is possible, it is recommended to leverage VM SKUs with Accelerated Networking feature. This feature does require specific VM SKU/size and OS versions, please see the list and requirement in the companion article.", - "guid": "b47a393a-0803-4272-a479-8b1578b219a4", - "id": "C01.13", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "3bd2a0a1-7e7a-48d9-8ae0-e37cee29711b", + "id": "F04.01", "services": [ - "VM", - "AVD" + "Subscriptions", + "AVS" ], - "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Use Azure VM SKUs able to leverage Accelerated Networking", + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "When intending to use automated scale-out, be sure to apply for sufficient Azure VMware Solution quota for the subscriptions running Azure VMware Solution", "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "For proper planning and deployment, it is important to assess the maximum number of concurrent and total users for each Host Pool. Additionally, users from different regions may require different Host Pools to ensure the best user experience.", - "guid": "bb91a33d-90ca-4e2c-a881-3706f7c0cb9f", - "id": "C02.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "d352caaa-b79b-4198-bab8-1932c9fc9d1b", + "id": "F04.02", "services": [ - "AVD" + "Storage", + "AVS", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Assess how many users will connect to AVD and from which regions", + "subcategory": "Automated Scale", + "text": "When intending to use automated scale-in, be sure to take storage policy requirements into account before performing such action", "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "The dependencies on resources external to the AVD pool should be assessed and reviewed, for example Active Directory, external file shares or other storage, on-premises services and resources, network infrastructure components like VPN and or ExpressRoute, external services and 3rd-party components. For all these resources, latency from the AVD Host Pool needs to be evaluated and connectivity considered. Additionally, BCDR considerations need to be applied to these dependencies as well.", - "guid": "6abca2a4-fda1-4dbf-9dc9-5d48c7c791dc", - "id": "C02.02", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop?toc=%2Fazure%2Fvirtual-desktop%2Ftoc.json&bc=%2Fazure%2Fvirtual-desktop%2Fbreadcrumb%2Ftoc.json", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "b78036f5-e6bf-4bb9-bd50-3547cc447e82", + "id": "F04.03", "services": [ - "AVD", - "ExpressRoute", - "VPN", - "Storage" + "AVS" ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Assess external dependencies for each Host Pool", + "subcategory": "Automated Scale", + "text": "Scaling operations always need to be serialized within a single SDDC as only one scale operation can be performed at a time (even when multiple clusters are used)", "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD offers a variety of client types (fat, thin, web) to connect over different platforms (Windows, MacOS, iOS, Android). Review limitations of each client and compare multiple options when possible.", - "guid": "a1f6d565-99e5-458b-a37d-4985e1112dbd", - "id": "C02.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/users/connect-windows", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "bf15bce2-19e4-4a0e-a588-79424d226786", + "id": "F04.04", "services": [ - "AVD" + "AVS" ], - "severity": "Low", - "subcategory": "Clients & Users", - "text": "Review user client OS used and AVD client type", + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Depending on the user locations, and AVD region deployment, users may have a non-optimal experience, hence is important to test as soon as possible in a small PoC environment. Run the 'Azure Virtual Desktop Experience Estimator' tool to select the best Azure region to deploy Host Pools. Beyond 150ms latency, user experience may be not optimal.", - "guid": "d2f54b29-769e-43a6-a1e8-838ac936667e", - "id": "C02.04", - "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "d20b56c5-7be5-4851-a0f8-3835c586cb29", + "id": "F04.05", "services": [ - "AVD" + "AVS" ], - "severity": "High", - "subcategory": "Clients & Users", - "text": "Run a PoC to validate end-to-end user experience and impact of network latency", + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Define and enforce scale in/out maximum limits for your environment in the automations", "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "RDP settings can currently only be configured at the host pool level, not per user/group. If different settings are required for different set of users, it is recommended to create multiple Host Pools.", - "guid": "3b365a5c-7acb-4e48-abe5-4cd79f2e8776", - "id": "C02.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/customize-rdp-properties", + "category": "Platform Automation", + "checklist": "Azure VMware Solution Design Review", + "guid": "1dc15a1c-075e-4e9f-841a-cccd579376bc", + "id": "F04.06", "services": [ - "AVD" + "Monitor", + "AVS" ], - "severity": "Low", - "subcategory": "Clients & Users", - "text": "Assess and document RDP settings for all user groups", - "waf": "Security" + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD is a non-regional service, Host Pools can be created in any region, automatic redirection from closest front-end will happen automatically.", - "guid": "42e52f47-21d9-428c-8b1b-d521e44a29a9", - "id": "C03.01", - "link": "https://azure.microsoft.com/global-infrastructure/services/?products=virtual-desktop", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hub provides encryption of data at rest. If you use your own key, the data is still encrypted using the Microsoft-managed key, but in addition the Microsoft-managed key will be encrypted using the customer-managed key. ", + "guid": "7aaf12e7-b94e-4f6e-847d-2d92981b1cd6", + "link": "https://learn.microsoft.com/azure/event-hubs/configure-customer-managed-key", "services": [ - "AVD" + "EventHubs" ], - "severity": "High", - "subcategory": "General", - "text": "Determine in which Azure regions AVD Host Pools will be deployed.", - "waf": "Performance" + "severity": "Low", + "subcategory": "Data Protection", + "text": "Use customer-managed key option in data at rest encryption when required", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD must store metadata to support the service; this is stored in the specified geography. However, this is independent of the regions where Host Pools are located.", - "guid": "bad37ead-53cc-47ce-8d7a-aab3571449ab", - "id": "C03.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/data-locations", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hubs namespaces permit clients to send and receive data with TLS 1.0 and above. To enforce stricter security measures, you can configure your Event Hubs namespace to require that clients send and receive data with a newer version of TLS. If an Event Hubs namespace requires a minimum version of TLS, then any requests made with an older version will fail. ", + "guid": "d2f54b29-769e-43a6-a0e7-828ac936657e", + "link": "https://learn.microsoft.com/azure/event-hubs/transport-layer-security-configure-minimum-version", "services": [ - "AVD" + "EventHubs" ], "severity": "Medium", - "subcategory": "General", - "text": "Determine metadata location for AVD service", - "waf": "Reliability" + "subcategory": "Data Protection", + "text": "Enforce a minimum required version of Transport Layer Security (TLS) for requests ", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Check for specific VM SKUs, especially if you need GPU or high-specs SKUs, and eventually Azure NetApp Files if used.", - "guid": "8053d89e-89dc-47b3-9be2-a1a27f7a9e91", - "id": "C03.03", - "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "When you create an Event Hubs namespace, a policy rule named RootManageSharedAccessKey is automatically created for the namespace. This policy has manage permissions for the entire namespace. It’s recommended that you treat this rule like an administrative root account and don’t use it in your application. Using AAD as an authentication provider with RBAC is recommended. ", + "guid": "13b0f566-4b1e-4944-a459-837ee79d6c6d", + "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature#shared-access-authorization-policies", "services": [ - "VM", - "AVD", - "Storage" + "AzurePolicy", + "TrafficManager", + "Entra", + "EventHubs", + "RBAC" ], - "severity": "Low", - "subcategory": "General", - "text": "Check Azure quotas and availability for specific VM sizes and types in the selected regions", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Identity and Access Management", + "text": "Avoid using root account when it is not necessary", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "AD DCs in Azure are recommended (at least two in different AZ) to reduce latency for users logging into AVD session hosts, and eventually for Azure NetApp Files and AD integration. A DC need to be able to talk to DCs for ALL child domains. As alternative, on-premise connectivity must be used to reach AD DCs.", - "guid": "c14aea7e-65e8-4d9a-9aec-218e6436b073", - "id": "D01.01", - "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Managed identities for Azure resources can authorize access to Event Hubs resources using Azure AD credentials from applications running in Azure Virtual Machines (VMs), Function apps, Virtual Machine Scale Sets, and other services. By using managed identities for Azure resources together with Azure AD authentication, you can avoid storing credentials with your applications that run in the cloud. ", + "guid": "3a365a5c-7acb-4e48-abd5-4cd79f2e8776", + "link": "https://learn.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest", "services": [ - "VNet", - "AVD", + "AKV", + "Storage", + "VM", "Entra", - "Storage" + "EventHubs" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create at least two Active Directory Domain Controllers (DCs) in Azure VNet environment close to AVD Host Pool", - "waf": "Reliability" + "subcategory": "Identity and Access Management", + "text": "When possible, your application should be using a managed identity to authenticate to Azure Event Hub. If not, consider having the storage credential (SAS, service principal credential) in Azure Key Vault or an equivalent service", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Recommended to create a separate OU per Host Pool under a separate OU hierarchy. These OUs will contain machine accounts of AVD Session Hosts. ", - "guid": "6db55f57-9603-4334-adf9-cc23418db612", - "id": "D01.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "When creating permissions, provide fine-grained control over a client's access to Azure Event Hub. Permissions in Azure Event Hub can and should be scoped to the individual resource level e.g. consumer group, event hub entity, event hub namespaces, etc.", + "guid": "8357c559-675c-45ee-a5b8-6ad8844ce3b2", + "link": "https://learn.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory#azure-built-in-roles-for-azure-event-hubs", "services": [ - "AVD", + "EventHubs", + "RBAC", "Entra" ], - "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a specific OU in Active Directory for each Host Pool", - "waf": "Operations" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "Use least privilege data plane RBAC", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Carefully review, and potentially block/filter inheritance of GPOs to the OUs containing AVD Host Pools. ", - "guid": "7126504b-b47a-4393-a080-327294798b15", - "id": "D01.03", - "link": "https://docs.microsoft.com/previous-versions/windows/desktop/Policy/group-policy-hierarchy", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hub resource logs include operational logs, virtual network and Kafka logs. Runtime audit logs capture aggregated diagnostic information for all data plane access operations (such as send or receive events) in Event Hubs.", + "guid": "b38b875b-a1cf-4104-a900-3a4d3ce474db", + "link": "https://learn.microsoft.com/azure/event-hubs/monitor-event-hubs-reference", "services": [ - "AVD", - "Entra" + "EventHubs", + "Monitor", + "VNet" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Review Domain GPOs that will be applied to OU and impacting Host Pool Session Hosts functionalities", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Enable logging for security investigation. Use Azure Monitor to captured metrics and logs such as resource logs, runtime audit logs and Kafka logs", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "If Active Directory Domain GPOs are used, it is recommended to configure FSLogix using the built-in provided GPO ADMX template referenced in the companion article in the 'More Info' column", - "guid": "2226a8e3-50a4-4ac3-8bd6-ee150553051f", - "id": "D01.04", - "link": "https://learn.microsoft.com/fslogix/how-to-use-group-policy-templates", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "Azure Event Hub by default has a public IP address and is Internet-reachable. Private endpoints allow traffic between your virtual network and Azure Event Hub traverses over the Microsoft backbone network. In addition to that, you should disable public endpoints if those are not used. ", + "guid": "5abca2a4-eda1-4dae-8cc9-5d48c6b791dc", + "link": "https://learn.microsoft.com/azure/event-hubs/private-link-service", "services": [ - "AVD", - "Entra" + "EventHubs", + "VNet", + "PrivateLink" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Configure FSLogix settings using the built-in provided GPO ADMX template", - "waf": "Operations" + "subcategory": "Networking", + "text": "Consider using private endpoints to access Azure Event Hub and disable public network access when applicable.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "It is recommended to have a specific dedicated account with minimal permissions, and without the default 10 joins limitation. Review the companion article for more details.", - "guid": "347dc560-28a7-41ff-b1cd-15dd2f0d5e77", - "id": "D01.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#session-hosts", + "category": "Security", + "checklist": "Azure Event Hub Review", + "description": "With IP firewall, you can restrict public endpoint further to only a set of IPv4 addresses or IPv4 address ranges in CIDR (Classless Inter-Domain Routing) notation. ", + "guid": "a0e6c465-89e5-458b-a37d-3974d1112dbd", + "link": "https://learn.microsoft.com/azure/event-hubs/event-hubs-ip-filtering", "services": [ - "VM", - "AVD", - "Entra" + "EventHubs" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a dedicated user account with only permissions to join VM to the domain", - "waf": "Security" + "subcategory": "Networking", + "text": "Consider only allowing access to Azure Event Hub namespace from specific IP addresses or ranges", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Avoid granting access per user, instead use AD groups and replicate them using Active Directory Connector (ADC) in Microsoft Entra ID (former Azure AD). ", - "guid": "2d41e361-1cc5-47b4-a4b1-410d43958a8c", - "id": "D01.06", - "link": "https://docs.microsoft.com/azure/virtual-desktop/manage-app-groups", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Apply guidance from the Microsoft cloud security benchmark related to Storage", + "guid": "d237de14-3b16-4c21-b7aa-9b64604489a8", + "id": "A01.01", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/storage-security-baseline", "services": [ - "AVD", - "Entra" + "Storage" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a domain user group for each set of users that will be granted access to each Host Pool Application Group (DAG or RAG)", + "subcategory": " Overview", + "text": "Consider the 'Azure security baseline for storage'", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "If Azure Files Active Directory (AD) integration is used, as part of the configuration procedure, an AD account to represent the storage account (file share) will be created. You can choose to register as a computer account or service logon account, see FAQ for details. For computer accounts, there is a default password expiration age set in AD at 30 days. Similarly, the service logon account may have a default password expiration age set on the AD domain or Organizational Unit (OU). For both account types, we recommend you check the password expiration age configured in your AD environment and plan to update the password of your storage account identity of the AD account before the maximum password age. You can consider creating a new AD Organizational Unit (OU) in AD and disabling password expiration policy on computer accounts or service logon accounts accordingly.", - "guid": "2289b3d6-b57c-4fc6-9546-1e1a3e3453a3", - "id": "D01.07", - "link": "https://docs.microsoft.com/azure/storage/files/storage-files-identity-ad-ds-enable", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Azure Storage by default has a public IP address and is Internet-reachable. Private endpoints allow to securely expose Azure Storage only to those Azure Compute resources that need access, thus eliminating exposure to the public Internet", + "guid": "f42d78e7-9d17-4a73-a22a-5a67e7a8ed4b", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/storage/common/storage-private-endpoints", "services": [ - "AVD", - "Entra", "Storage", - "AzurePolicy" + "PrivateLink" ], "severity": "High", - "subcategory": "Active Directory", - "text": "Review your organization password expiration policy for accounts used by Azure Files AD integration", + "subcategory": "Networking", + "text": "Consider using private endpoints for Azure Storage", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "You can configure this using Active Directory Connect (ADC) or Azure AD Domain Services (for hybrid or cloud organizations). Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", - "guid": "5119bf8e-8f58-4542-a7d9-cec166cd072a", - "id": "D01.08", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Newly created storage accounts are created using the ARM deployment model, so that RBAC, auditing etc. are all enabled. Ensure that there are no old storage accounts with classic deployment model in a subscription", + "guid": "30e37c3e-2971-41b2-963c-eee079b598de", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/virtual-machines/migration-classic-resource-manager-overview#migration-of-storage-accounts", "services": [ - "AVD", - "Entra" + "Subscriptions", + "RBAC", + "Storage" ], - "severity": "High", - "subcategory": "Active Directory", - "text": "A Windows Server Active Directory forest/domain must be in sync with Microsoft Entra ID", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Governance", + "text": "Ensure older storage accounts are not using 'classic deployment model'", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "If Azure Files is used and pre-requisites can be satisfied, it is recommended to configure (Microsoft Entra ID) Kerberos authentication. This configuration will allow to store FSLogix profiles that can be accessed by hybrid user identities from Azure AD-joined session hosts without requiring network line-of-sight to domain controllers.", - "guid": "e777fd5e-c5f1-4d6e-8fa9-fc210b88e338", - "id": "D02.01", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-identity-auth-hybrid-identities-enable", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Leverage Microsoft Defender to learn about suspicious activity and misconfigurations.", + "guid": "fc5972cd-4cd2-41b0-a803-7f5e6b4bfd3d", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/storage/common/azure-defender-storage-configure", "services": [ - "AVD", - "Entra", + "Defender", "Storage" ], - "severity": "Medium", - "subcategory": "Microsoft Entra ID", - "text": "Configure Azure Files share for Microsoft Entra ID (former Azure AD) Kerberos authentication on Microsoft Entra ID Joined scenario", + "severity": "High", + "subcategory": "Governance", + "text": "Enable Microsoft Defender for all of your storage accounts", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "An Azure subscription must be parented to the same Microsoft Entra ID (former Azure AD) tenant, that contains a virtual network that either contains or is connected to the Windows Server Active Directory Domain Services or Microsoft Entra ID Domain Services instance.", - "guid": "6ceb5443-5125-4922-9442-93bb628537a5", - "id": "D03.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "The soft-delete mechanism allows to recover accidentally deleted blobs.", + "guid": "503547c1-447e-4c66-828a-7100f1ce16dd", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-overview", "services": [ - "VNet", - "Subscriptions", - "AVD", - "Entra" + "Storage" ], - "severity": "High", - "subcategory": "Requirements", - "text": "A Microsoft Entra ID tenant must be available with at least one subscription linked", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Data Availability", + "text": "Enable 'soft delete' for blobs", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop supports different types of identities depending on which configuration you choose. Please review the supported scenarios mentioned in the 'More Info' article and document the design decision accordingly in the 'Comment' column. Critically, external identities (B2B or B2C) are not supported. Be sure to review also the list of supported scenarios in https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios.", - "guid": "b4ce4781-7557-4a1f-8043-332ae199d44c", - "id": "D03.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Consider selectively disabling 'soft delete' for certain blob containers, for example if the application must ensure that deleted information is immediately deleted, e.g. for confidentiality, privacy or compliance reasons. ", + "guid": "3f1d5e87-2e52-4e36-81cc-58b4a4b1510e", + "id": "A05.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-enable", "services": [ - "AVD", - "Entra" + "Storage" ], - "severity": "High", - "subcategory": "Requirements", - "text": "Review and document your identity scenario", + "severity": "Medium", + "subcategory": "Confidentiality", + "text": "Disable 'soft delete' for blobs", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Users need accounts that are in Microsoft Entra ID (former Azure AD). If you're also using AD DS or Azure AD Domain Services in your deployment of Azure Virtual Desktop, these accounts will need to be hybrid identities, which means the user accounts are synchronized. If you're using Microsoft Entra ID with AD DS, you'll need to configure Azure AD Connect to synchronize user identity data between AD DS and Microsoft Entra ID. If you're using Microsoft Entra ID with Azure AD Domain Services, user accounts are synchronized one way from Microsoft Entra ID to Azure AD Domain Services. This synchronization process is automatic. AVD also supports Microsoft Entra ID native accounts with some restrictions. External identities (B2B or B2C) are not supported.", - "guid": "f9b141a8-98a5-435e-9378-97e71ca7da7b", - "id": "D03.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Soft delete for containers enables you to recover a container after it has been deleted, for example recover from an accidental delete operation.", + "guid": "43a58a9c-2289-4c3d-9b57-d0c655462f2a", + "id": "A06.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-overview", "services": [ - "AVD", - "Entra" + "Storage" ], - "severity": "Medium", - "subcategory": "Requirements", - "text": "Assess User Account types and requirements", + "severity": "High", + "subcategory": "Data Availability", + "text": "Enable 'soft delete' for containers", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD supports SSO using either Active Directory Federation Services (AD FS) or Microsoft Entra ID (former Azure AD) authentication. The latter is recommended, please check the requirements and limitation in the 'More Info' article. Using AD FS could be a viable choice if already present in the customer environment, it is not recommended to deploy a brand new ADFS infrastructure just for AVD SSO implementation.", - "guid": "5f9f680a-ba07-4429-bbf7-93d7071561f4", - "id": "D03.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication#single-sign-on-sso", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Consider selectively disabling 'soft delete' for certain blob containers, for example if the application must ensure that deleted information is immediately deleted, e.g. for confidentiality, privacy or compliance reasons. ", + "guid": "3e3453a3-c863-4964-ab65-2d6c15f51296", + "id": "A07.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-enable", "services": [ - "AVD", - "Entra" + "Storage" ], "severity": "Medium", - "subcategory": "Requirements", - "text": "If Single-Sign On (SSO) is a requirement, review the supported scenarios and prerequisites", - "waf": "Reliability" + "subcategory": "Confidentiality", + "text": "Disable 'soft delete' for containers", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "VMs can be Windows Active Directory (AD) domain-joined, Hybrid AD-joined, Microsoft Entra ID (former Azure AD) Joined or Azure AD Domain Services joined. Be sure to review supported scenarios, limitations and requirements from the referenced article.", - "guid": "ea962a15-9394-46da-a7cc-3923266b2258", - "id": "D03.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Prevents accidental deletion of a storage account, by forcing the user to first remove the deletion lock, prior to deletion", + "guid": "5398e6de-d227-4dd1-92b0-6c21d7999a64", + "id": "A08.01", + "link": "https://learn.microsoft.com/azure/storage/common/lock-account-resource", "services": [ - "VM", - "AVD", - "Entra" + "Storage" ], "severity": "High", - "subcategory": "Requirements", - "text": "Select the proper AVD Session Host domain join type", + "subcategory": "Data Availability", + "text": "Enable resource locks on storage accounts", "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Compare self-managed Windows Active Directory Domain Services, Microsoft Entra ID (former Azure AD), and managed Azure AD Domain Services (AAD-DS)", - "guid": "6f4a1651-bddd-4ea8-a487-cdeb4861bc3b", - "id": "D03.06", - "link": "https://docs.microsoft.com/azure/active-directory-domain-services/compare-identity-solutions", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Consider 'legal hold' or 'time-based retention' policies for blobs, so that is is impossible to delete the blob, the container, or the storage account. Please note that 'impossible' actually means 'impossible'; once a storage account contains an immutable blob, the only way to 'get rid' of that storage account is by cancelling the Azure subscription.", + "guid": "6f4389a8-f42c-478e-98c0-6a73a22a4956", + "id": "A09.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/immutable-storage-overview", "services": [ - "AVD", - "Entra" + "Subscriptions", + "Storage", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Requirements", - "text": "Before using Azure AD Domain Services (AAD-DS) for AVD, be sure to review the limitations.", - "waf": "Reliability" + "severity": "High", + "subcategory": "Data Availability, Compliance", + "text": "Consider immutable blobs", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD provides administrative templates for Intune and Active Directory GPO. Using these templates it is possible to centrally control several AVD configuration settings: Graphics related data logging, Screen capture protection, RDP Shortpath for managed networks, Watermarking. See companion article in 'More Info' colum for details. NOTE: FSLogix has its own separate template.", - "guid": "5549524b-36c0-4f1a-892b-ab3ca78f5db2", - "id": "E01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/administrative-template", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Consider disabling unprotected HTTP/80 access to the storage account, so that all data transfers are encrypted, integrity protected, and the server is authenticated. ", + "guid": "e7a8dc4a-20e2-47c3-b297-11b1352beee0", + "id": "A10.01", + "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", "services": [ - "AVD", - "Entra", - "Monitor" + "Storage" ], - "severity": "Low", - "subcategory": "Management", - "text": "Use built-in provided administrative templates for AVD settings configuration", - "waf": "Operations" + "severity": "High", + "subcategory": "Networking", + "text": "Require HTTPS, i.e. disable port 80 on the storage account", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Determine if a configuration management tool is already in place to manage Host Pool VM configuration after initial deployment, For example SCCM/SCOM, Intune/ConfigurationManager, 3rd-party solutions.", - "guid": "3334fdf9-1c23-4418-8b65-285269440b4b", - "id": "E01.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/management", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "When configuring a custom domain (hostname) on a storage account, check whether you need TLS/HTTPS; if so, you might have to put Azure CDN in front of your storage account.", + "guid": "79b588de-fc49-472c-b3cd-21bf77036e5e", + "id": "A10.02", + "link": "https://learn.microsoft.com/azure/storage/blobs/storage-custom-domain-name", "services": [ - "VM", - "AVD", - "Monitor" + "Storage" ], - "severity": "Low", - "subcategory": "Management", - "text": "Plan AVD Session Hosts configuration management strategy", - "waf": "Operations" + "severity": "High", + "subcategory": "Networking", + "text": "When enforcing HTTPS (disabling HTTP), check that you do not use custom domains (CNAME) for the storage account.", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "We recommend using Microsoft Intune, if requirements can be satisfied, to manage your Azure Virtual Desktop environment. Review supported scenarios and requirements to enable Intune for AVD Session Host management in the referenced article in the “More Info” column. Document your choice in the 'Comment' column. In that article, review the different requirements and capabilities for single-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop and multi-session https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session AVD.", - "guid": "63a08be1-6004-4b4a-a79b-f3239faae113", - "id": "E01.03", - "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Requiring HTTPS when a client uses a SAS token to access blob data helps to minimize the risk of credential loss.", + "guid": "6b4bed3d-5035-447c-8347-dc56028a71ff", + "id": "A10.03", + "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview", "services": [ - "AVD", - "Monitor" + "Storage" ], "severity": "Medium", - "subcategory": "Management", - "text": "Evaluate Intune for AVD Session Hosts management", - "waf": "Operations" + "subcategory": "Networking", + "text": "Limit shared access signature (SAS) tokens to HTTPS connections only", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "The scaling tool provides a low-cost automation option for customers who want to optimize their session host VM costs. You can use the scaling tool to schedule VMs to start and stop based on Peak and Off-Peak business hours, scale out VMs based on number of sessions per CPU core, scale in VMs during Off-Peak hours, leaving the minimum number of session host VMs running. Not available yet for Personal Host Pool type.", - "guid": "7138b820-102c-4e16-be30-1e6e872e52e3", - "id": "E01.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/autoscale-scenarios", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "AAD tokens should be favored over shared access signatures, wherever possible", + "guid": "e1ce15dd-3f0d-45e7-92d4-1e3611cc57b4", + "id": "A11.01", + "link": "https://learn.microsoft.com/azure/storage/common/authorize-data-access", "services": [ - "VM", - "AVD", - "Cost", - "Monitor" + "Storage", + "Entra" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Assess the requirements for host pool auto-scaling capability", - "waf": "Reliability" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "Use Azure Active Directory (Azure AD) tokens for blob access", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Start VM On Connect lets you reduce costs by enabling end users to turn on their session host virtual machines (VMs) only when they need them. You can then turn off VMs when they're not needed. You can configure Start VM on Connect for personal or pooled host pools using the Azure portal or PowerShell. Start VM on Connect is a host pool wide setting.", - "guid": "55f612fe-f215-4f0d-a956-10e7dd96bcbc", - "id": "E01.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "When assigning a role to a user, group, or application, grant that security principal only those permissions that are necessary for them to perform their tasks. Limiting access to resources helps prevent both unintentional and malicious misuse of your data.", + "guid": "a4b1410d-4395-48a8-a228-9b3d6b57cfc6", + "id": "A11.02", "services": [ - "VM", - "AVD", - "Cost", - "Monitor" + "RBAC", + "Storage", + "Entra" ], - "severity": "Low", - "subcategory": "Management", - "text": "Consider the usage of Start VM on Connect for Personal Host Pools", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Identity and Access Management", + "text": "Least privilege in IaM permissions", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "'Start VM On Connect' provides a smart way to automatically start previously stopped Session Hosts but does not provide a mechanism to shut down when not in used. Administrators are encouraged to configure additional policies to sign users out of their sessions and run Azure automation scripts to de-allocate VMs. Users should be not allowed to shut down their Personal Hosts since will not be able to de-allocate Azure VMs, then billing will still be active with no cost reduction.", - "guid": "79a686ea-d971-4ea0-a9a8-1aea074c94cb", - "id": "E01.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect-faq#are-vms-automatically-deallocated-when-a-user-stops-using-them", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "A user delegation SAS is secured with Azure Active Directory (Azure AD) credentials and also by the permissions specified for the SAS. A user delegation SAS is analogous to a service SAS in terms of its scope and function, but offers security benefits over the service SAS. ", + "guid": "55461e1a-3e34-453a-9c86-39648b652d6c", + "id": "A11.03", + "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json#best-practices-when-using-sas", "services": [ - "VM", - "Cost", - "Monitor", - "AVD", - "AzurePolicy" + "Storage", + "Entra" ], - "severity": "Low", - "subcategory": "Management", - "text": "Evaluate the implementation of an ad-hoc mechanism to shut down Personal AVD Session Hosts", - "waf": "Cost" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "When using SAS, prefer 'user delegation SAS' over storage-account-key based SAS.", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop billing is mainly based on cost associated to compute, networking and storage resources consumed by Host Pools. In addition to this, costs can be generated by dependent resources, for example VPN or ExpressRoute or vWAN, Active Directory Domain Controllers, DNS, etc. There is no direct cost associated to AVD objects like workspaces, host pools or application groups. To make AVD associated costs more evident and grouped by Host Pool, it is recommended to use 'cm-resource-parent' tag. ", - "guid": "51bcafca-476a-48fa-9b91-9645a7679f20", - "id": "E01.07", - "link": "https://learn.microsoft.com/azure/virtual-desktop/tag-virtual-desktop-resources", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Storage account keys ('shared keys') have very little audit capabilities. While it can be monitored on who/when fetched a copy of the keys, once the keys are in the hands of multiple people, it is impossible to attribute usage to a specific user. Solely relying on AAD authentication makes it easier to tie storage access to a user. ", + "guid": "15f51296-5398-4e6d-bd22-7dd142b06c21", + "id": "A11.04", + "link": "https://learn.microsoft.com/rest/api/storageservices/authorize-with-shared-key", "services": [ - "VPN", - "Storage", - "Cost", "Monitor", - "ExpressRoute", - "AVD", - "DNS", - "VWAN" + "AKV", + "Storage", + "Entra" ], - "severity": "Low", - "subcategory": "Management", - "text": "Review and adopt suggested Azure Tags for Azure Virtual Desktop", - "waf": "Cost" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "Consider disabling storage account keys, so that only AAD access (and user delegation SAS) is supported.", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Advisor analyzes your configurations and telemetry to offer personalized recommendations to solve common problems. With these recommendations, you can optimize your Azure resources for reliability, security, operational excellence, performance, and cost.", - "guid": "611dd68c-5a4b-4252-8e44-a59a9c2399c4", - "id": "E01.08", - "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-advisor-recommendations", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Use Activity Log data to identify 'when', 'who', 'what' and 'how' the security of your storage account is being viewed or changed (i.e. storage account keys, access policies, etc.).", + "guid": "d7999a64-6f43-489a-af42-c78e78c06a73", + "id": "A12.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/blob-storage-monitoring-scenarios#audit-account-activity", "services": [ - "AVD", - "Entra", - "Cost", - "Monitor" + "Monitor", + "AKV", + "Storage", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Management", - "text": "Periodically check Azure Advisor recommendations for AVD", - "waf": "Operations" + "severity": "High", + "subcategory": "Monitoring", + "text": "Consider using Azure Monitor to audit control plane operations on the storage account", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Customers have several options: Microsoft Configuration Manager, this article explains how to automatically apply updates to a Azure Virtual Desktop session hosts running Windows 10/11: https://learn.microsoft.com/azure/virtual-desktop/configure-automatic-updates, Microsoft Intune: https://docs.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session, Azure Update Management and WSUS for Windows Server OS only (client OS not supported: https://learn.microsoft.com/azure/automation/update-management/operating-system-requirements), 3rd Party tools. Outside an emergency security patching situation, it is recommended to move away from an 'in-place' update strategy patching strategy and adopt a re-imaging approach.", - "guid": "04722da2-9c2b-41cd-922f-54b29bade3aa", - "id": "E01.09", - "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop-multi-session", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "A key expiration policy enables you to set a reminder for the rotation of the account access keys. The reminder is displayed if the specified interval has elapsed and the keys have not yet been rotated.", + "guid": "a22a4956-e7a8-4dc4-a20e-27c3e29711b1", + "id": "A13.01", + "link": "https://learn.microsoft.com/azure/storage/common/storage-account-keys-manage?tabs=azure-portal#create-a-key-expiration-policy", "services": [ - "AVD", - "Monitor" + "AKV", + "Storage", + "Entra", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Management", - "text": "Plan for a Session Host emergency patching and update strategy", - "waf": "Operations" + "subcategory": "Identity and Access Management", + "text": "When using storage account keys, consider enabling a 'key expiration policy'", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "The Scheduled Agent Updates feature lets you create up to two maintenance windows per Host Pool to update AVD components at a convenient time. It is recommended to specify maintenance windows then upgrading Session Hosts will not happen during peak business hours. Scheduled Agent Updates is disabled by default. This means that, unless you enable this setting, the agent can get updated at any time by the agent update flighting service.", - "guid": "c067939b-e5ca-4698-b9ce-3bd91843e73f", - "id": "E01.10", - "link": "https://learn.microsoft.com/azure/virtual-desktop/scheduled-agent-updates", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "A SAS expiration policy specifies a recommended interval over which the SAS is valid. SAS expiration policies apply to a service SAS or an account SAS. When a user generates service SAS or an account SAS with a validity interval that is larger than the recommended interval, they'll see a warning.", + "guid": "352beee0-79b5-488d-bfc4-972cd3cd21bf", + "id": "A13.02", + "link": "https://learn.microsoft.com/azure/storage/common/sas-expiration-policy", "services": [ - "AVD", - "Monitor" + "Storage", + "Entra", + "AzurePolicy" ], - "severity": "Low", - "subcategory": "Management", - "text": "Configure the Scheduled Agent Updates feature", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Identity and Access Management", + "text": "Consider configuring an SAS expiration policy", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Host pools are a collection of one or more identical virtual machines within Azure Virtual Desktop environment. We highly recommend you create a validation host pool where service updates are applied first. This allows you to monitor service updates before the service applies them to your standard or non-validation environment.", - "guid": "d1e8c38e-c936-4667-913c-005674b1e944", - "id": "E01.11", - "link": "https://docs.microsoft.com/azure/virtual-desktop/create-validation-host-pool", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Stored access policies give you the option to revoke permissions for a service SAS without having to regenerate the storage account keys. ", + "guid": "77036e5e-6b4b-4ed3-b503-547c1347dc56", + "id": "A13.03", + "link": "https://learn.microsoft.com/rest/api/storageservices/define-stored-access-policy", "services": [ - "VM", - "AVD", - "Monitor" + "AKV", + "Storage", + "Entra", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Management", - "text": "Create a validation (canary) Host Pool", - "waf": "Operations" + "subcategory": "Identity and Access Management", + "text": "Consider linking SAS to a stored access policy", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "An AVD Host Pool can be deployed in several ways: Azure Portal, ARM templates, Azure CLI tool, Powershell, manual VM creation with registration token, Terraform, 3rd-party tools. It is important to adopt proper method/s to support automatic deployment through automation and CI/CD tools.", - "guid": "a459c373-e7ed-4616-83b3-65a917ecbe48", - "id": "E01.12", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-platform-automation-and-devops", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "guid": "028a71ff-e1ce-415d-b3f0-d5e772d41e36", + "id": "A14.01", + "link": "https://microsoft.github.io/code-with-engineering-playbook/continuous-integration/dev-sec-ops/secret-management/recipes/detect-secrets-ado/", "services": [ - "VM", - "AVD", - "Monitor" + "AKV", + "Storage" ], "severity": "Medium", - "subcategory": "Management", - "text": "Determine Host Pool deployment strategy", - "waf": "Operations" + "subcategory": "CI/CD", + "text": "Consider configuring your application's source code repository to detect checked-in connection strings and storage account keys.", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "After you register a VM to a host pool within the Azure Virtual Desktop service, the agent regularly refreshes the VM's token whenever the VM is active. The certificate for the registration token is valid for 90 days. Because of this 90-day limit, we recommend VMs to be online for 20 minutes every 90 days so that the machine can refresh its tokens and update the agent and side-by-side stack components.", - "guid": "ebe54cd7-df2e-48bb-ac35-81559bb9153e", - "id": "E01.13", - "link": "https://docs.microsoft.com/azure/virtual-desktop/faq", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Ideally, your application should be using a managed identity to authenticate to Azure Storage. If that is not possible, consider having the storage credential (connection string, storage account key, SAS, service principal credential) in Azure KeyVault or an equivalent service.", + "guid": "11cc57b4-a4b1-4410-b439-58a8c2289b3d", + "id": "A15.01", + "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-storage-keys", "services": [ - "VM", - "AVD", - "Monitor" + "Storage", + "Entra" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Turn on Session Host VMs at least every 90 days for token refresh", - "waf": "Operations" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "Consider storing connection strings in Azure KeyVault (in scenarios where managed identities are not possible)", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop Insights is a dashboard built on Azure Monitor Workbooks that helps IT professionals understand their Azure Virtual Desktop environments. Read the referenced article to learn how to set up Azure Monitor for Azure Virtual Desktop to monitor your AVD environments.", - "guid": "63cfff1c-ac59-49ef-8d5a-83dd4de36c1c", - "id": "E02.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/insights", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Use near-term expiration times on an ad hoc SAS service SAS or account SAS. In this way, even if a SAS is compromised, it's valid only for a short time. This practice is especially important if you cannot reference a stored access policy. Near-term expiration times also limit the amount of data that can be written to a blob by limiting the time available to upload to it.", + "guid": "27138b82-1102-4cac-9eae-01e6e842e52f", + "id": "A15.02", + "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", "services": [ - "AVD", - "Monitor" + "Storage", + "Entra", + "AzurePolicy" ], "severity": "High", - "subcategory": "Monitoring", - "text": "Enable monitoring for AVD", - "waf": "Reliability" + "subcategory": "Identity and Access Management", + "text": "Strive for short validity periods for ad-hoc SAS", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Virtual Desktop uses Azure Monitor and Log Analytics for monitoring and alerts like many other Azure services. This lets admins identify issues through a single interface. The service creates activity logs for both user and administrative actions. Each activity log falls under the following categories: Management, Feed, Connections, Host Registration, Errors, Checkpoints. ", - "guid": "81770afb-c4c0-4e43-a186-58d2857ed671", - "id": "E02.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "When creating a SAS, be as specific and restrictive as possible. Prefer a SAS for a single resource and operation over a SAS which gives much broader access.", + "guid": "4721d928-c1b1-4cd5-81e5-4a29a9de399c", + "id": "A15.03", + "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", "services": [ - "VM", - "AVD", - "Monitor" + "Storage", + "Entra" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable diagnostic settings for Workspaces, Host Pools, Application Groups and Host VMs to Log Analytics workspace", - "waf": "Reliability" + "subcategory": "Identity and Access Management", + "text": "Apply a narrow scope to a SAS", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "See the referenced article and this additional one to setup proper monitoring and alerting for storage: https://docs.microsoft.com/azure/storage/files/storage-troubleshooting-files-performance. ", - "guid": "2463cffe-179c-4599-be0d-5973dd4ce32c", - "id": "E02.03", - "link": "https://docs.microsoft.com/azure/storage/files/storage-files-monitoring?tabs=azure-portal", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "A SAS can include parameters on which client IP addresses or address ranges are authorized to request a resource using the SAS. ", + "guid": "fd7b28dc-9355-4562-82bf-e4564b0d834a", + "id": "A15.04", + "link": "https://learn.microsoft.com/rest/api/storageservices/create-account-sas", "services": [ - "AVD", "Storage", - "Monitor" + "Entra" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Create alerts on the profile storage to be alerted in case of high usage and throttling", - "waf": "Reliability" + "subcategory": "Identity and Access Management", + "text": "Consider scoping SAS to a specific client IP address, wherever possible", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "You can use Azure Service Health to monitor service issues and health advisories for Azure Virtual Desktop. Azure Service Health can notify you with different types of alerts (for example, email or SMS), help you understand the effect of an issue, and keep you updated as the issue resolves.", - "guid": "18813706-f7c4-4c0d-9e51-4548d2457ed6", - "id": "E02.04", - "link": "https://docs.microsoft.com/azure/virtual-desktop/set-up-service-alerts", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "A SAS cannot constrain how much data a client uploads; given the pricing model of amount of storage over time, it might make sense to validate whether clients uploaded maliciously large contents.", + "guid": "348b263e-6dd6-4051-8a36-498f6dbad38e", + "id": "A15.05", "services": [ - "AVD", - "Monitor" + "Storage", + "Entra" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Configure Azure Service Health for AVD alerts ", - "waf": "Reliability" + "severity": "Low", + "subcategory": "Identity and Access Management", + "text": "Consider checking uploaded data, after clients used a SAS to upload a file. ", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "If required to connect to on-premises environment, assess the current connectivity option or plan for the required connectivity (ExpressRoute, Azure S2S or 3rd-party NVA VPN). ", - "guid": "dd399cfd-7b28-4dc8-9555-6202bfe4563b", - "id": "F01.01", - "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "When accessing blob storage via SFTP using a 'local user account', the 'usual' RBAC controls do not apply. Blob access via NFS or REST might be more restrictive than SFTP access. Unfortunately, as of early 2023, local users are the only form of identity management that is currently supported for the SFTP endpoint", + "guid": "ad53cc7c-e1d7-4aaa-a357-1449ab8053d8", + "id": "A15.06", + "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-support#sftp-permission-model", "services": [ - "NVA", - "AVD", - "ExpressRoute", - "VPN" + "RBAC", + "Storage", + "Entra" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Determine if hybrid connectivity is required to connect to on-premises environment", - "waf": "Reliability" + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "SFTP: Limit the amount of 'local users' for SFTP access, and audit whether access is needed over time.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD Host Pools can be deployed in either Azure Virtual WAN or traditional 'Hub & Spoke' network topologies. It is recommended to deploy each Host Pool in a separate 'spoke' VNet, using 'hub' is not recommended.", - "guid": "c8639648-a652-4d6c-85e5-02965388e5de", - "id": "F01.02", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-network-topology-and-connectivity", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "guid": "9f89dc7b-33be-42a1-a27f-7b9e91be1f38", + "id": "A15.07", + "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-known-issues#authentication-and-authorization", "services": [ - "VNet", - "AVD", - "VWAN" + "Storage", + "Entra" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Determine Azure Virtual Network (VNet) placement for each AVD Host Pool", - "waf": "Performance" + "subcategory": "Identity and Access Management", + "text": "SFTP: The SFTP endpoint does not support POSIX-like ACLs.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Evaluate the bandwidth requirements, ensure VPN/ER bandwidth will be enough, ensure proper routing and firewall rules are in place, test end-to-end latency. ", - "guid": "d227dd14-2b06-4c21-a799-9a646f4389a7", - "id": "F01.03", - "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Storage supports CORS (Cross-Origin Resource Sharing), i.e. an HTTP feature that enables web apps from a different domain to loosen the same-origin policy. When enabling CORS, keep the CorsRules to the least privilege.", + "guid": "cef39812-bd46-43cb-aac8-ac199ebb91a3", + "id": "A16.01", + "link": "https://learn.microsoft.com/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services", "services": [ - "AVD", - "VPN" + "Storage", + "AzurePolicy" ], - "severity": "Medium", + "severity": "High", "subcategory": "Networking", - "text": "Assess which on-premises resources are required from AVD Host Pools", - "waf": "Reliability" + "text": "Avoid overly broad CORS policies", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Several options are available. You can use Azure Firewall or equivalent 3rd-party NVA, Network Security Group (NSG) and/or Proxy servers. NSG is not able to enable/disable by URL, only ports and protocols. Proxy should be used only as explicit setting in user browser. Details on using Azure Firewall Premium with AVD are reported in the companion article in the 'More Info' column. Be sure to allow proper access to required AVD URLs. Forced Tunneling to on-premises is not recommended.", - "guid": "fc4972cd-3cd2-41bf-9703-6e5e6b4bed3d", - "id": "F01.04", - "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Data at rest is always encrypted server-side, and in addition might be encrypted client-side as well. Server-side encryption might happen using a platform-managed key (default) or customer-managed key. Client-side encryption might happen by either having the client supply an encryption/decryption key on a per-blob basis to Azure storage, or by completely handling encryption on the client-side. thus not relying on Azure Storage at all for confidentiality guarantees.", + "guid": "3d90cae2-cc88-4137-86f7-c0cbafe61464", + "id": "A17.01", + "link": "https://learn.microsoft.com/azure/storage/common/storage-service-encryption", "services": [ - "VNet", - "Firewall", - "AVD", - "NVA" + "Storage" ], - "severity": "Medium", - "subcategory": "Networking", - "text": "Need to control/restrict Internet outbound traffic for AVD hosts?", + "severity": "High", + "subcategory": "Confidentiality and Encryption", + "text": "Determine how data at rest should be encrypted. Understand the thread model for data.", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Required URLs for AVD control plane access by session hosts are documented here: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list. A check tool is available to verify connectivity from the session hosts: https://docs.microsoft.com/azure/virtual-desktop/safe-url-list#required-url-check-tool. Forced Tunneling to on-premises is not recommended.", - "guid": "65c7acbe-45bb-4e60-ad89-f2e87778424d", - "id": "F01.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/safe-url-list", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "guid": "8dd457e9-2713-48b8-8110-2cac6eae01e6", + "id": "A17.02", + "link": "https://learn.microsoft.com/azure/storage/common/customer-managed-keys-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&bc=%2Fazure%2Fstorage%2Fblobs%2Fbreadcrumb%2Ftoc.json", "services": [ - "AVD" + "Storage" ], - "severity": "High", - "subcategory": "Networking", - "text": "Ensure AVD control plane endpoints are accessible", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Confidentiality and Encryption", + "text": "Determine which/if platform encryption should be used.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Consider the usage of Azure Defender Endpoint or similar 3rd-party agents to control user web navigation, see the Security section for more details.", - "guid": "73676ae4-6691-4e88-95ad-a42223e13810", - "id": "F01.06", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/onboard-windows-multi-session-device?view=o365-worldwide", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "guid": "e842e52f-4721-4d92-ac1b-1cd521e54a29", + "id": "A17.03", + "link": "https://learn.microsoft.com/azure/storage/blobs/encryption-customer-provided-keys", "services": [ - "AVD", - "Defender" + "Storage" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Need to control/restrict Internet outbound traffic only for users on AVD hosts? ", + "subcategory": "Confidentiality and Encryption", + "text": "Determine which/if client-side encryption should be used.", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Custom UDR and NSG can be applied to AVD Host Pool subnets, for example to redirect to Azure Firewall or NVA, or to filter/block network traffic. In this case is recommended to carefully review to ensure optimal path for outbound traffic to AVD control plane is used. Service Tags can now be used with UDR and NSG, then AVD management plane traffic can be easily allowed: https://learn.microsoft.com/azure/virtual-desktop/safe-url-list.", - "guid": "523181a9-4174-4158-93ff-7ae7c6d37431", - "id": "F01.07", - "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "category": "Security", + "checklist": "Azure Blob Storage Review", + "description": "Leverage Resource Graph Explorer (resources | where type == 'microsoft.storage/storageaccounts' | where properties['allowBlobPublicAccess'] == true) to find storage accounts which allow anonymous blob access.", + "guid": "659ae558-b937-4d49-a5e1-112dbd7ba012", + "id": "A18.01", + "link": "https://learn.microsoft.com/azure/storage/blobs/anonymous-read-access-configure?tabs=portal#allow-or-disallow-public-read-access-for-a-storage-account", "services": [ - "VNet", - "Firewall", - "AVD", - "NVA" + "Storage", + "Entra" ], - "severity": "Low", - "subcategory": "Networking", - "text": "Review custom UDR and NSG for AVD Host Pool subnets", + "severity": "High", + "subcategory": "Identity and Access Management", + "text": "Consider whether public blob access is needed, or whether it can be disabled for certain storage accounts. ", "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Network traffic from AVD Session Host VMs to AVD control plane should be as direct as possible. Redirecting this traffic through a Proxy or Firewall with deep packet inspection and/or SSL termination could cause serious issues and bad customer experience. It is recommended to bypass Proxy and Firewall just for the AVD control plane. User generated traffic surfing the web instead, should be filtered by Firewall and/or redirected to a Proxy. For details and guidelines, please see the companion article in the 'More Info' column.", - "guid": "cc6edca0-aeca-4566-9e92-cf246f1465af", - "id": "F01.08", - "link": "https://learn.microsoft.com/azure/virtual-desktop/proxy-server-support", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "aff6691b-4935-4ada-9222-3ece81b12318", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "services": [ - "VM", - "AVD" + "ASR" ], - "severity": "High", - "subcategory": "Networking", - "text": "Do not use Proxy servers, SSL termination and Deep Packet Inspection for AVD control plane traffic", - "waf": "Reliability" + "severity": "Medium", + "subcategory": " ", + "text": "Do not combine ASCS and Database cluster on to single/same VM" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "It is recommended to assess and review networking bandwidth requirements for users, based on the specific workload type. The referenced article provide general estimations and recommendations, but specific measure are required for proper sizing. ", - "guid": "516785c6-fa96-4c96-ad88-408f372734c8", - "id": "F01.09", - "link": "https://learn.microsoft.com/azure/virtual-desktop/rdp-bandwidth", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "1a541741-5833-4fb4-ae3c-2df743165c3a", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "services": [ - "VM", - "AVD" + "LoadBalancer", + "ASR" ], - "severity": "Low", - "subcategory": "Networking", - "text": "Check the network bandwidth required for each user and in total for the VM SKU", - "waf": "Performance" + "severity": "Medium", + "subcategory": " ", + "text": "Make sure the Floating IP is enabled on the Load balancer" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "If Azure Files SMB share will be used to store user profiles via FSLogix, the usage of Private Endpoint (PE) for private access to the storage is recommended. AVD Session Hosts will access the storage using a private IP in the same VNet, a separate subnet is recommended. This feature has an additional cost that must be evaluated. If PE will not be used, at least Service Endpoint is recommended (no cost associated).", - "guid": "ec27d589-9178-426d-8df2-ff60020f30a6", - "id": "F01.10", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-networking-endpoints", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "cbe05bbe-209d-4490-ba47-778424d11678", + "link": "https://learn.microsoft.com/azure/security-center/", "services": [ - "Storage", - "Cost", - "PrivateLink", - "VNet", - "AVD" + "VM", + "RBAC", + "Entra", + "ASR" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Evaluate usage Private Endpoint for Azure Files share", - "waf": "Security" + "subcategory": " ", + "text": "Do not mix servers of different roles in the same availability set. Keep central services VMs, database VMs, application VMs in their own availability sets" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Connections to Azure Virtual Desktop can use TCP or UDP. RDP Shortpath is a feature of AVD that establishes a direct UDP-based transport between a supported Windows Remote Desktop client and session host. if clients have line of sight to AVD session hosts from internal network (VPN usage is not recommended), this feature can provide lower latency and best performances as explained in https://learn.microsoft.com/azure/virtual-desktop/rdp-shortpath?tabs=managed-networks#key-benefits.", - "guid": "b2074747-d01a-4f61-b1aa-92ad793d9ff4", - "id": "F01.11", - "link": "https://docs.microsoft.com/azure/virtual-desktop/shortpath", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "5d2fa56c-56ad-4484-88fe-72734c486ba2", + "link": "https://learn.microsoft.com/azure/security-center/", "services": [ - "AVD", - "VPN" + "SAP", + "ACR", + "ASR" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Evaluate usage of RDP ShortPath for clients connecting from managed internal networks", - "waf": "Performance" + "subcategory": " ", + "text": "Use one proximity placement group per SAP SID. Groups don't span across Availability Zones or Azure regions" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Security mechanisms provided by GPO should be used, if available. For example, it is possible to impose desktop screen lock and idle session disconnection time. Existing GPOs applied to on-premises environment should be reviewed and eventually applied also to secure also AVD Hosts when joined to the domain.", - "guid": "a135e337-897e-431c-97d6-8cb6a22ac19f", - "id": "G01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#establish-maximum-inactive-time-and-disconnection-policies", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "80dc0591-cf65-4de8-b130-9cccd579266b", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "AVD" + "VM", + "Entra", + "ASR" ], "severity": "Medium", - "subcategory": "Active Directory", - "text": "Review Active Directory GPO to secure RDP sessions", - "waf": "Security" + "subcategory": " ", + "text": "Azure doesn't currently support combining ASCS and db HA in the same Linux Pacemaker cluster; separate them into individual clusters. However, you can combine up to five multiple central-services clusters into a pair of VMs." }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Microsoft Defender for Endpoint supports Azure Virtual Desktop for Windows 10/11 Enterprise multi-session. Check article for onboarding non-persistent virtual desktop infrastructure (VDI) devices: https://docs.microsoft.com/windows/security/threat-protection/microsoft-defender-atp/configure-endpoints-vdi", - "guid": "b1172576-9ef6-4691-a483-5ac932223ece", - "id": "G02.01", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/deployment-vdi-microsoft-defender-antivirus", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "cca275fa-a1ab-4fe9-b55d-04c3c4919cb1", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "services": [ - "AVD", - "Defender" + "LoadBalancer", + "ASR" ], - "severity": "High", - "subcategory": "Host Configuration", - "text": "Ensure anti-virus and anti-malware solutions are used", - "waf": "Security" + "severity": "Medium", + "subcategory": " ", + "text": "Use a Standard Load Balancer SKU in front of ASCS and DB clusters" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Disks in Azure are already encrypted at rest by default with Microsoft managed keys. Host VM OS disk encryption is possible and supported using Azure Disk Encryption (ADE - BitLocker) and Disk Encryption Set (DES - Server Side Encryption), the latter is recommended. Encryption of FSLogix storage using Azure Files can be done using SSE on Azure Storage. For OneDrive encryption, see this article: https://docs.microsoft.com/compliance/assurance/assurance-encryption-for-microsoft-365-services.", - "guid": "0fd32907-98bc-4178-adc5-a06ca7144351", - "id": "G02.02", - "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "b3d1325a-e124-4ba3-9df6-85eddce9bd3b", + "link": "https://www.microsoft.com/itshowcase/implementing-a-zero-trust-security-model-at-microsoft", "services": [ "VM", - "AVD", "Storage", - "AKV" + "ASR" ], - "severity": "Low", - "subcategory": "Host Configuration", - "text": "Assess disk encryption requirements for AVD Session Hosts", - "waf": "Security" + "severity": "Medium", + "subcategory": " ", + "text": "Both VMs in the HA pair should be deployed in an availability set, or Availability Zones should be the same size and have the same storage configuration" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Trusted launch are Gen2 Azure VMs with enhanced security features aimed to protect against “bottom of the stack” threats through attack vectors such as rootkits, boot kits, and kernel-level malware. Recommended to enable and leverage Secure Boot, Virtual TPM (vTPM) and Integrity Monitoring.", - "guid": "36a5a67f-bb9e-4d5b-9547-8c4479816b28", - "id": "G02.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#azure-virtual-desktop-support-for-trusted-launch", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "b0cdb3b5-5eb2-4ec1-9eea-a3592829e2ed", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "services": [ - "VM", - "AVD", - "Monitor" + "ASR" ], "severity": "Medium", - "subcategory": "Host Configuration", - "text": "Enable Trusted launch in Azure Gen2 VM Session Hosts", - "waf": "Security" + "subcategory": " ", + "text": "Native database replication technology should be used to synchronize the database in a HA pair." }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Trusted Launch and Gen2 VM are not only security and performance enhancing features but also system requirements for Windows 11. When building an AVD environment based on Windows 11, it is essential to enable these features.", - "guid": "135d3899-4b31-44d3-bc8f-028871a359d8", - "id": "G02.04", - "link": "https://learn.microsoft.com/windows/whats-new/windows-11-requirements", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "b2173676-aff6-4691-a493-5ada42223ece", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "services": [ - "VM", - "AVD" + "SAP", + "ASR" ], - "severity": "High", - "subcategory": "Host Configuration", - "text": "Enable Trusted Launch and use Gen2 image are system requirements for Windows 11", - "waf": "Security" + "severity": "Medium", + "subcategory": " ", + "text": "Perform a point-in-time recovery for your production databases at any point and in a time frame that meets your RTO; point-in-time recovery typically includes operator errors deleting data either on the DBMS layer or through SAP, incidentally" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Displayed content will be automatically blocked or hidden in screenshots. Keep in mind screen sharing will also be blocked when using Teams or other collaboration software which use screen sharing.", - "guid": "a49dc137-7896-4343-b2bc-1a31bf1d30b6", - "id": "G02.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/screen-capture-protection", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "81b12318-1a54-4174-8583-3fb4ae3c2df7", "services": [ - "AVD" - ], - "severity": "Low", - "subcategory": "Host Configuration", - "text": "Consider enabling screen capture protection to prevent sensitive information from being captured", - "waf": "Security" + "VNet", + "ASR" + ], + "severity": "Medium", + "subcategory": " ", + "text": "The CIDR for the primary virtual network (VNet) shouldn't conflict or overlap with the CIDR of the DR site's Vnet" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "If not absolutely required, redirecting drives, printers, and USB devices to a user's local device in a remote desktop session should be disabled or highly restricted. Restrict Windows Explorer access by hiding local and remote drive mappings is also a secure measure to adopt preventing users from discovering unwanted information about system configuration and users.", - "guid": "7ce2cd20-85b4-4f82-828e-6558736ede6a", - "id": "G02.06", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#other-security-tips-for-session-hosts", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "43165c3a-cbe0-45bb-b209-d490da477784", "services": [ - "AVD" + "VM", + "Entra", + "ASR" ], "severity": "Medium", - "subcategory": "Host Configuration", - "text": "Restrict device redirection and drive mapping", - "waf": "Security" + "subcategory": " ", + "text": "Use Site Recovery to replicate an application server to a DR site. Site Recovery can also help with replicating central-services cluster VMs to the DR site. When you invoke DR, you'll need to reconfigure the Linux Pacemaker cluster on the DR site (for example, replace the VIP or SBD, run corosync.conf, and more)." }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "When choosing a deployment model, you can either provide remote users access to entire virtual desktops or only select applications. Remote applications, or RemoteApps, provide a seamless experience as the user works with apps on their virtual desktop. RemoteApps reduce risk by only letting the user work with a subset of the remote machine exposed by the application.", - "guid": "4e25d70e-3924-44f4-b66f-d6cdd4f4a973", - "id": "G03.01", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "24d11678-5d2f-4a56-a56a-d48408fe7273", "services": [ - "AVD" + "ASR" ], "severity": "Medium", - "subcategory": "Management", - "text": "When possible, prefer Remote Apps over Full Desktops (DAG)", - "waf": "Security" + "subcategory": " ", + "text": "Native database replication should be used to synchronize data to the DR site, rather than Azure Site Recovery" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Web content filtering feature provided by Web Protection capability in Microsoft Defender for Endpoint, can be used to to control user web navigation. If this tool is used, configuration of web filtering for user Internet browsing is recommended. Access by the Guest OS system to required AVD control plane URLs must be guaranteed.", - "guid": "e19dd344-29eb-4722-a237-a151c5bb4e4f", - "id": "G03.02", - "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", + "category": "Compute", + "checklist": "Azure Landing Zone Review", + "guid": "2829e2ed-b217-4367-9aff-6691b4935ada", "services": [ - "AVD", - "Defender" + "VM" ], "severity": "Medium", - "subcategory": "Management", - "text": "Need to control/restrict user Internet navigation from AVD session hosts?", - "waf": "Security" + "subcategory": " ", + "text": "Make quota requests for correct VM SKU and Zones" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "We recommend you don't grant your users admin access to virtual desktops. If you need software packages, we recommend you make them available through configuration management utilities.", - "guid": "a0cdb3b5-4eb2-4eb0-9dda-a3592718e2ed", - "id": "G03.03", - "link": "https://docs.microsoft.com/azure/virtual-desktop/security-guide", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", + "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", "services": [ - "AVD" + "Subscriptions", + "RBAC", + "Entra" ], "severity": "High", - "subcategory": "Management", - "text": "Ensure AVD users will not have local administrator privileges on AVD Hosts", - "waf": "Security" + "subcategory": "Identity", + "text": "Enforce a RBAC model for management groups, subscriptions, resource groups and resources", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "We recommend you enable Defender for Cloud for the subscriptions, virtual machines, key vaults, and storage accounts used by AVD. With this tool is possible to assess and manage vulnerabilities, assess compliance with common frameworks like PCI, strengthen the overall security of your AVD environment and measure it over time using 'Secure Score': https://learn.microsoft.com/azure/virtual-desktop/security-guide#improve-your-secure-score.", - "guid": "1814387e-5ca9-4c26-a9b3-2ab5bdfc6998", - "id": "G03.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#enable-microsoft-defender-for-cloud", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "45911475-e39e-4530-accc-d979366bcda2", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "services": [ - "VM", - "Storage", - "AVD", - "Defender", - "AKV", - "Subscriptions" + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Management", - "text": "Enable Microsoft Defender for Cloud to manage AVD Session Hosts security posture", - "waf": "Security" + "subcategory": "Identity", + "text": "Enforce Principle propagation for forwarding the identity from SAP cloud application to SAP on-premises (Including IaaS) through cloud connector", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Enabling audit log collection lets you view user and admin activity related to Azure Virtual Desktop and store in a central repository like Log Analytics workspace. ", - "guid": "a0916a76-4980-4ad0-b278-ee293c1bc352", - "id": "G03.05", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#collect-audit-logs", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "services": [ - "AVD", - "Entra", - "Monitor" + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Management", - "text": "Enable diagnostic and audit logging", - "waf": "Security" + "subcategory": "Identity", + "text": "Implement SSO to SAP SaaS applications like SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics and SAP C4C with Azure AD using SAML." }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Assign the least privilege required by defining administrative, operations, and engineering roles to Azure RBAC roles. To limit access to high privilege roles within your Azure Virtual Desktop landing zone, consider integration with Azure Privileged Identity Management (PIM). Maintaining knowledge of which team is responsible for each particular administrative area helps you determine Azure role-based access control (RBAC) roles and configuration.", - "guid": "baaab757-1849-4ab8-893d-c9fc9d1bb73b", - "id": "G03.06", - "link": "https://docs.microsoft.com/azure/virtual-desktop/rbac", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "services": [ - "AVD", - "RBAC", + "SAP", "Entra" ], - "severity": "Low", - "subcategory": "Management", - "text": "Assess the requirement to use custom RBAC roles for AVD management", - "waf": "Security" + "severity": "Medium", + "subcategory": "Identity", + "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD users should not have permission to install application. If required, Windows Defender Application Control (WDAC) can be used to control which drivers and applications are allowed to run on their Windows clients. ", - "guid": "b9ea80c8-0628-49fc-ae63-125aa4c0a284", - "id": "G03.07", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#windows-defender-application-control", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "9eb54dad-7861-4e1c-973a-f3bb003fc9c1", "services": [ - "AVD", - "Defender" + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Management", - "text": "Restrict users from installing un-authorized applications", - "waf": "Security" + "subcategory": "Identity", + "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Enabling MFA and CA lets you manage risks before you grant users access to your AVD environment. When deciding which users to grant access to, we recommend you also consider who the user is, how they sign in, and which device they're using. Additional details and configuration procedures are provided in the companion article. Microsoft Entra ID is the new name for Azure Active Directory (Azure AD).", - "guid": "916d697d-8ead-4ed2-9bdd-186f1ac252b9", - "id": "G04.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-mfa", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "services": [ - "AVD", + "SAP", "Entra" ], "severity": "Medium", - "subcategory": "Microsoft Entra ID", - "text": "Evaluate the usage of Multi-Factor Authentication (MFA) and Conditional Access (CA) for AVD users", - "waf": "Security" + "subcategory": "Identity", + "text": "You can implement SSO to SAP GUI by using SAP NetWeaver SSO or a partner solution.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "If Zero Trust is a requirement, review the companion article in the 'More Info' column. It provides steps to apply the principles of Zero Trust to an Azure Virtual Desktop deployment.", - "guid": "221102d0-90af-49fc-b2b7-8d3fe397e43", - "id": "G05.01", - "link": "https://learn.microsoft.com/security/zero-trust/azure-infrastructure-avd", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "23181aa4-1742-4694-9ff8-ae7d7d474317", "services": [ - "AVD" + "AKV", + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Zero Trust", - "text": "Review and Apply Zero Trust principles and guidance", - "waf": "Security" + "subcategory": "Identity", + "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution.", + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "If used, make sure to check the list of best practices and recommendations described in the referenced article.", - "guid": "9164e990-9ae2-48c8-9c33-b6b7808bafe6", - "id": "H01.01", - "link": "https://learn.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files#best-practices-for-azure-virtual-desktop", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "6c8bcbf4-5bbe-4609-b8a0-3e97778424d6", + "link": "https://blogs.sap.com/2017/07/12/sap-single-sign-on-protect-your-sap-landscape-with-x.509-certificates/", "services": [ - "AVD", - "Storage" + "AKV", + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Azure Files", - "text": "Check best-practices for Azure Files", - "waf": "Performance" + "subcategory": "Identity", + "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "SMB Multichannel enables clients to use multiple network connections that provide increased performance while lowering the cost of ownership. Increased performance is achieved through bandwidth aggregation over multiple NICs and utilizing Receive Side Scaling (RSS) support for NICs to distribute the IO load across multiple CPUs.", - "guid": "5784b6ca-5e9e-4bcf-8b54-c95459ea7369", - "id": "H01.02", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-smb-multichannel-performance", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "16785d6f-a96c-496a-b885-18f482734c88", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", "services": [ - "AVD", - "ACR", - "Storage", - "Cost" + "SAP", + "Entra" ], - "severity": "Low", - "subcategory": "Azure Files", - "text": "Enable SMB multichannel when using a premium file share to host FSLogix profile containers.", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Identity", + "text": "Implement SSO by using OAuth for SAP NetWeaver to allow third-party or custom applications to access SAP NetWeaver OData services." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "If a second region is required for DR purposes verify NetApp availability in there as well.", - "guid": "4a359836-ee79-4d6c-9d3a-364a5b7abae3", - "id": "H02.01", - "link": "https://azure.microsoft.com/global-infrastructure/services/", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "a747c350-8d4c-449c-93af-393dbca77c48", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", + "services": [ + "SAP", + "Entra" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "Implement SSO to SAP HANA" + }, + { + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", "services": [ - "AVD", - "Storage" + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Azure NetApp Files", - "text": "If NetApp Files storage is required, check storage service availability in your specific region.", - "waf": "Reliability" + "subcategory": "Identity", + "text": "Consider Azure AD an identity provider for SAP systems hosted on RISE. For more information, see Integrating the Service with Azure AD." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "CA option is a recommended setting in the FSLogix scenario, as it enables a more resilient SMB session between the Session Host and NetApp Files.", - "guid": "a2661898-866a-4c8d-9d1f-8cfc86e88024", - "id": "H02.02", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-fslogix-profile-container", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "e4e48226-ce54-44b6-bb6b-bfa15bd8f753", + "link": "https://github.com/azuredevcollege/SAP/blob/master/sap-oauth-saml-flow/README.md", "services": [ - "AVD", - "Storage" + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Azure NetApp Files", - "text": "If NetApp Files storage is used enable CA (Continuous Availability) option to increase resiliency", - "waf": "Reliability" + "subcategory": "Identity", + "text": "For applications that access SAP, you might want to use principal propagation to establish SSO." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "An Active Directory Site should be created for the Azure virtual network environment where Azure NetApp Files (ANF) subnet will be created, and that site name should be specified in the ANF connection property when executing the join procedure as explained in the reference article.", - "guid": "6647e977-db49-48a8-bc35-743f17499d42", - "id": "H02.03", - "link": "https://docs.microsoft.com/azure/azure-netapp-files/create-active-directory-connections", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", "services": [ - "VNet", - "AVD", - "Storage" + "SAP", + "Entra" ], - "severity": "High", - "subcategory": "Azure NetApp Files", - "text": "If Azure NetApp Files storage is used, check Active Directory Site name setting in the Active Directory Connection configuration", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Identity", + "text": "If you're using SAP BTP services or SaaS solutions that require SAP Identity Authentication Service (IAS), consider implementing SSO between SAP Cloud Identity Authentication Services and Azure AD to access those SAP services. This integration lets SAP IAS act as a proxy identity provider and forwards authentication requests to Azure AD as the central user store and identity provider." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Possible options: Standard HDD, Standard SSD, or Premium SSD. Ephemeral disks are not supported, Ultra-Disks not recommended. Recommended to evaluate Premium for OS disk if user density is not low, and if Cloud Cache will be used. ", - "guid": "3611c818-b0a0-4bc5-80e4-3a18a9cd289c", - "id": "H03.01", - "link": "https://docs.microsoft.com/azure/virtual-machines/disks-types", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", "services": [ - "AVD", - "Storage" + "SAP", + "Entra" ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Determine which type of managed disk will be used for the Session Hosts", - "waf": "Performance" + "subcategory": "Identity", + "text": "Implement SSO to SAP BTP" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Possible options are: Azure NetApp Files, Azure Files, VM based File Server. File-server it is not recommended. Azure Files Premium typically a good starting point. NetApp usually required for large scale / high-performant environment. For a detailed comparison see the article in the 'More Info' column.", - "guid": "ed6b17db-8255-4462-b2ae-e4553afc8339", - "id": "H03.02", - "link": "https://docs.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "01f11b7f-38df-4251-9c76-4dec19abd3e8", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-successfactors-inbound-provisioning-cloud-only-tutorial", "services": [ - "VM", - "AVD", - "Storage" + "SAP", + "Entra" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Determine which storage backend solution will be used for FSLogix Profiles", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Identity", + "text": "If you're using SAP SuccessFactors, consider using the Azure AD automated user provisioning. With this integration, as you add new employees to SAP SuccessFactors, you can automatically create their user accounts in Azure AD. Optionally, you can create user accounts in Microsoft 365 or other SaaS applications that are supported by Azure AD. Use write-back of the email address to SAP SuccessFactors." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Every Host Pool should use a separate set of storage accounts/volumes (at least one) and shares. Users should have a different profile for each Host Pool since settings and configurations are specific to each Host Pool. Additionally, accessing different Host Pools at the same time can cause errors on the shared user profile VHD/X. Usage of different storage accounts/volumes for multiple shares is also recommended to scale independently.", - "guid": "2fad62bd-5004-453c-ace4-64d862e7f5a4", - "id": "H03.03", - "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "6ba28021-4591-4147-9e39-e5309cccd979", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "services": [ - "AVD", - "Storage" + "Subscriptions", + "SAP", + "AzurePolicy" ], - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Do not share storage and profiles between different Host Pools", - "waf": "Performance" + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "enforce existing Management Group policies to SAP Subscriptions", + "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "As a starting point for estimating profile container storage performance requirements we recommend to assume 10 IOPS per user in the steady state and 50 IOPS per user during sign-in/sign-out. Space requirements is simply obtained based on the maximum profiles size in FSLogix per the total number of users for each Host Pool. Multiple storage accounts can be used for the same Host Pool if required.", - "guid": "680e7828-9c93-4665-9d02-bff4564b0d93", - "id": "H03.04", - "link": "https://learn.microsoft.com/azure/virtual-desktop/faq#what-s-the-largest-profile-size-fslogix-can-handle-", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", "services": [ - "AVD", - "Storage" + "Subscriptions", + "SAP" ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "Verify storage scalability limits and Host Pool requirements", - "waf": "Reliability" + "subcategory": "Subscriptions", + "text": "Integrate tightly coupled applications into the same SAP subscription to avoid additional routing and management complexity", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Avoid introducing additional latency and costs associated with cross-region network traffic where possible.", - "guid": "8aad53cc-79e2-4e86-9673-57c549675c5e", - "id": "H03.05", - "link": "https://docs.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", "services": [ - "AVD", - "Storage", - "Cost" + "Subscriptions" ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "For optimal performance, the storage solution and the FSLogix profile container should be in the same Azure region.", - "waf": "Performance" + "subcategory": "Subscriptions", + "text": "Leverage Subscription as scale unit and scaling our resources, consider deploying subscription per environment eg. Sandbox, non-prod, prod ", + "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "The recommendation in Azure Virtual Desktop is to use Profile Container without Office Container (ODFC) split unless you are planning for specific Business Continuity and Disaster Recovery (BCDR) scenarios as described in the Disaster Recovery section below. https://docs.microsoft.com/fslogix/profile-container-office-container-cncpt ", - "guid": "df47d2d9-2881-4b1c-b5d1-e54a29759e39", - "id": "H04.01", - "link": "https://learn.microsoft.com/fslogix/concepts-container-types#when-to-use-profile-and-odfc-containers", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", + "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", "services": [ - "AVD", - "Storage", - "ASR" + "Subscriptions", + "VM" ], "severity": "High", - "subcategory": "FSLogix", - "text": "Do not use Office Containers (ODFC) if not strictly required and justified", - "waf": "Reliability" + "subcategory": "Subscriptions", + "text": "Ensure quota increase as a part of subscription provisioning (e.g. total available VM cores within a subscription)", + "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Make sure to configure the following antivirus exclusions for FSLogix Profile Container virtual hard drives, as documented in the referenced article in the 'More Info' column.", - "guid": "83f63047-22ee-479d-9b5c-3632054b69ba", - "id": "H04.02", - "link": "https://learn.microsoft.com/fslogix/overview-prerequisites#configure-antivirus-file-and-folder-exclusions", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", + "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", "services": [ - "AVD", - "Storage" + "Subscriptions" ], - "severity": "Medium", - "subcategory": "FSLogix", - "text": "Configure the recommended antivirus exclusions for FSLogix (includes not scanning VHD(x) files on connect).", - "waf": "Security" + "severity": "Low", + "subcategory": "Subscriptions", + "text": "The Quota API is a REST API that you can use to view and manage quotas for Azure services. Consider using it if necessary." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Profile containers have a default max size of 30GB. If large Profile Containers are anticipated, and customers wants to try to keep them small, consider using OneDrive to host Office 365 files outside the FSLogix profile.", - "guid": "01e6a84d-e5df-443d-8992-481718d5d1e5", - "id": "H04.03", - "link": "https://docs.microsoft.com/fslogix/profile-container-configuration-reference", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", + "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", "services": [ - "AVD", - "Storage" + "Subscriptions", + "VM" ], "severity": "High", - "subcategory": "FSLogix", - "text": "Review and confirm configured maximum profile size in FSLogix", - "waf": "Cost" + "subcategory": "Subscriptions", + "text": "If deploying to an availability zone, ensure that the VM's zone deployment is available once the quota has been approved. Submit a support request with the subscription, VM series, number of CPUs and availability zone required." }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Defaults and recommended settings are reported in the companion article in the 'More Info' column. If not recommended keys and/or values must be used, be sure to review with a Microsoft AVD expert and clearly document your choices.", - "guid": "d34aad5e-8c78-4e1d-9666-7313c405674c", - "id": "H04.04", - "link": "https://learn.microsoft.com/fslogix/concepts-configuration-examples", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "e6e20617-3686-4af4-9791-f8935ada4332", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", "services": [ - "AVD", - "ACR", - "Storage", - "AKV" + "Subscriptions" ], "severity": "High", - "subcategory": "FSLogix", - "text": "Review FSLogix registry keys and determine which ones to apply", - "waf": "Reliability" + "subcategory": "Subscriptions", + "text": "Ensure required services and features are available within the chosen deployment regions eg. ANF , Zone etc.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Concurrent or multiple connections are not recommended in Azure Virtual Desktop. Concurrent connections are also not supported by Session Hosts running in an Azure Virtual Desktop Host Pool. OneDrive, if used, doesn't support concurrent or multiple connections using the same container, under any circumstance. For multiple connections, usage of the same profile disk is not recommended.", - "guid": "5e985b85-9c77-43e7-b261-623b775a917e", - "id": "H04.05", - "link": "https://learn.microsoft.com/fslogix/concepts-multi-concurrent-connections", + "category": "Management Group and Subscriptions", + "checklist": "Azure Landing Zone Review", + "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", "services": [ - "AVD", - "Storage" + "TrafficManager", + "Subscriptions", + "Cost" ], - "severity": "High", - "subcategory": "FSLogix", - "text": "Avoid usage of concurrent or multiple connections", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Leverage Azure resource tag for cost categorization and resource grouping (: BillTo, Department (or Business Unit), Environment (Production, Stage, Development), Tier (Web Tier, Application Tier), Application Owner, ProjectName)", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Cloud Cache uses OS drive as local cache storage and may generate lot of pressure on the VM disk. Depending on the VM SKU and size used, the VM temporary drive can be a viable and performant solution where to relocate Cloud Cache cached content. Before adopting this solution, tests should be executed to confirm performance and stability. More details on Cloud Cache can be found here: https://learn.microsoft.com/fslogix/concepts-fslogix-cloud-cache. ", - "guid": "b2d1215a-e114-4ba3-9df5-85ecdcd9bd3b", - "id": "H04.06", - "link": "https://docs.microsoft.com/fslogix/cloud-cache-configuration-reference", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "2f7c95f0-6e15-44e3-aa35-92829e6e2061", + "link": "https://learn.microsoft.com/azure/backup/sap-hana-database-about", "services": [ - "VM", - "AVD", - "Storage" + "Monitor", + "Backup" ], - "severity": "Low", - "subcategory": "FSLogix", - "text": "If FSLogix Cloud Cache is used, consider moving the cache directory to the VM temporary drive.", - "waf": "Performance" + "severity": "High", + "subcategory": "BCDR", + "text": "Help protect your HANA database by using the Azure Backup service.", + "training": "https://learn.microsoft.com/training/modules/implement-azure-backup-sap-workloads-azure-virtual-machines/?source=recommendations" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "REDIRECTION.XML file is used to control what folders are redirected out of the profile container to the 'C:' drive. Exclusions should be the exception and should never be used unless the specific exclusion is completely understood by the person configuring the exclusion. Exclusions should always be fully tested in the environment where they are intended to be implemented. Configuring exclusions may impact functionality, stability and performance.", - "guid": "0b50ca97-b1d2-473c-b4d9-6e98b0f912de", - "id": "H04.07", - "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt#redirectionsxml", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "302a2fbf-3745-4a5f-a365-c9d1a16ca22c", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/azacsnap-introduction", "services": [ - "AVD", - "Storage" + "Monitor", + "VM", + "Storage", + "Entra" ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "Review the usage of FSLogix redirection.", - "waf": "Cost" + "subcategory": "BCDR", + "text": "If you deploy Azure NetApp Files for your HANA, Oracle, or DB2 database, use the Azure Application Consistent Snapshot tool (AzAcSnap) to take application-consistent snapshots. AzAcSnap also supports Oracle databases. Consider using AzAcSnap on a central VM rather than on individual VMs." }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "Define a resource group structure for placement of Azure Arc-enabled servers resources", - "guid": "585e1112-9bd7-4ba0-82f7-b94ef6e043d2", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "42d37218-a3a7-45df-bff6-1173e7f249ea", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", "services": [ - "Arc" + "Monitor", + "SAP" ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "One or more resource groups is required for onboarding servers into Azure", - "waf": "Operations" + "subcategory": "Management", + "text": "Ensure time-zone matches between the operating system and the SAP system." }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "guid": "aa359271-8e6e-4205-8725-769e46691e88", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "c3c7abc0-716c-4486-893c-40e181d65539", + "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel-multi-sid", "services": [ - "Entra", - "Arc" + "Monitor", + "Entra" ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Take Azure Active Directory object limitations into account", - "waf": "Performance" + "subcategory": "Management", + "text": "Don't group different application services in the same cluster. For example, don't combine DRBD and central services clusters on the same cluster. However, you can use the same Pacemaker cluster to manage approximately five different central services (multi-SID cluster).", + "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "The following resource providers needs to be registered: Microsoft.HybridCompute, Microsoft.GuestConfiguration, Microsoft.HybridConnectivity", - "guid": "deace4bb-1deb-44c6-9fc3-fc14eeaa3692", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-resource-providers", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "a491dfc4-9353-4213-9217-eef0949f9467", + "link": "https://azure.microsoft.com/pricing/offers/dev-test/", "services": [ - "Subscriptions", - "Arc" + "Monitor", + "Cost" ], - "severity": "High", - "subcategory": "General", - "text": "Has the Resource providers required been registered in all subscriptions", - "waf": "Operations" + "severity": "Low", + "subcategory": "Management", + "text": "Consider running dev/test systems in a snooze model to save and optimize Azure run costs." }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "Aligning with an existing or creating an Azure tagging strategy is recommended. Resource tags allow you to quickly locate it, automate operational tasks amd more. ", - "guid": "c6d37331-65c7-4acb-b44b-be609d79f2e8", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "b7056168-6199-4732-a514-cdbb2d5c9c54", + "link": "https://learn.microsoft.com/azure/lighthouse/overview", "services": [ - "Arc" + "Monitor", + "SAP", + "Entra" ], - "severity": "Low", - "subcategory": "General", - "text": "Has a tagging strategy for Azure Arc-enabled servers been defined", - "waf": "Cost" + "severity": "Medium", + "subcategory": "Management", + "text": "If you partner with customers by managing their SAP estates, consider Azure Lighthouse. Azure Lighthouse allows managed service providers to use Azure native identity services to authenticate to the customers' environment. It puts the control in the hands of customers, because they can revoke access at any time and audit service providers' actions." }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "Installation of the connected machine agent is supported on most newer Windows and Linux operative systems, review the link to se the latest list", - "guid": "7778424c-5167-475c-9fa9-5b96ad88408e", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#supported-operating-systems", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "4d116785-d2fa-456c-96ad-48408fe72734", + "link": "https://learn.microsoft.com/azure/update-manager/scheduled-patching?tabs=schedule-updates-single-machine%2Cschedule-updates-scale-overview", "services": [ - "Arc" + "Monitor", + "VM" ], - "severity": "High", - "subcategory": "General", - "text": "What operating systems need to be Azure Arc-enabled", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Management", + "text": "Use Azure Update Manager to check the status of available updates for a single VM or multiple VMs and consider scheduling regular patching.", + "training": "https://learn.microsoft.com/training/modules/keep-your-virtual-machines-updated/?source=recommendations" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "There are software requirements to the agent installation. Some might require a system reboot after installation, review to link", - "guid": "372734b8-76ba-428f-8145-901365d38e53", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#software-requirements", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "76c8bcbf-45bb-4e60-ad8a-03e97778424d", + "link": "https://learn.microsoft.com/azure/sap/workloads/lama-installation", "services": [ - "Arc" + "Monitor", + "SAP" ], - "severity": "High", - "subcategory": "General", - "text": "Are required software installed on Windows and Linux servers to support the installation", - "waf": "Operations" + "severity": "Low", + "subcategory": "Management", + "text": "Optimize and manage SAP Basis operations by using SAP Landscape Management (LaMa). Use the SAP LaMa connector for Azure to relocate, copy, clone, and refresh SAP systems.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-remote-management/?source=recommendations" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "guid": "d44c7c89-19ca-41f6-b521-5ae514ba34d4", - "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=azure-arc®ions=all", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "14591147-5e39-4e53-89cc-cd979366bcda", + "link": "https://learn.microsoft.com/azure/sap/monitor/about-azure-monitor-sap-solutions", "services": [ - "Arc" + "SQL", + "Monitor", + "SAP" ], - "severity": "High", - "subcategory": "General", - "text": "Make sure to use a supported Azure region", - "waf": "Reliability" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Monitor for SAP solutions to monitor your SAP workloads(SAP HANA, high-availability SUSE clusters, and SQL systems) on Azure. Consider supplementing Azure Monitor for SAP solutions with SAP Solution Manager.", + "training": "https://learn.microsoft.com/training/modules/implement-azure-monitoring-sap-workloads-azure-virtual-machines/?source=recommendations" }, { - "category": "Foundation", - "checklist": "Azure Arc Review", - "description": "The scope include organization into management groups, subscriptions, and resource groups.", - "guid": "f9ccbd86-8266-4abc-a264-f9a19bf39d95", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/organize-inventory-servers#organize-resources-with-built-in-azure-hierarchies", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "2750ab1a-b039-4d95-b54c-7c8929cb107d", + "link": "https://learn.microsoft.com/azure/sap/workloads/vm-extension-for-sap", "services": [ - "Subscriptions", - "Arc" + "Monitor", + "VM", + "SAP", + "Entra" ], - "severity": "Low", - "subcategory": "Organization", - "text": "Define the structure for Azure management of resources", - "waf": "Performance" + "severity": "High", + "subcategory": "Monitoring", + "text": "Run a VM Extension for SAP check. VM Extension for SAP uses the assigned managed identity of a virtual machine (VM) to access VM monitoring and configuration data. The check ensures that all performance metrics in your SAP application come from the underlying Azure Extension for SAP.", + "training": "https://learn.microsoft.com/training/modules/configure-azure-enhanced-monitoring-extension-for-sap/?source=recommendations" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Define RBAC rules to the servers / resource groups as required for servers management, the 'Azure Connected Machine Resource Administrator' or 'Hybrid Server Resource Administrator' role would be sufficient for management of the Azure Arc-enabled servers resources in Azure", - "guid": "9bf39d95-d44c-47c8-a19c-a1f6d5215ae5", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#identity-and-access-control", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "5325ae52-5ba3-44d4-985e-2213ace7bb12", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "services": [ - "RBAC", - "Entra", - "Arc" + "Monitor", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Access", - "text": "Assign RBAC rights to Azure AD user/group access for managing Azure Arc-enabled servers", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Use Azure Policy for access control and compliance reporting. Azure Policy provides the ability to enforce organization-wide settings to ensure consistent policy adherence and fast violation detection. ", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "guid": "14ba34d4-585e-4111-89bd-7ba012f7b94e", - "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-nonaad", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "523181aa-4174-4269-93ff-8ae7d7d47431", + "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-overview", "services": [ - "Entra", - "Arc", - "AKV" + "Monitor", + "SAP", + "NetworkWatcher" ], - "severity": "Low", - "subcategory": "Access", - "text": "Consider using managed identities for applications to access Azure resources like Key Vault example in link", - "waf": "Security" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Connection Monitor in Azure Network Watcher to monitor latency metrics for SAP databases and application servers. Or collect and display network latency measurements by using Azure Monitor.", + "training": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/collecting-and-displaying-niping-network-latency-measurements/ba-p/1833979" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "An Azure subscription must be parented to the same Azure AD tenant", - "guid": "35ac9322-23e1-4380-8523-081a94174158", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "d89fd98d-23e4-4b40-a92e-32db9365522c", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-monitor-and-troubleshoot", "services": [ - "Subscriptions", - "Entra", - "Arc" + "Monitor", + "SAP", + "ASR" ], "severity": "High", - "subcategory": "Requirements", - "text": "An Azure Active Directory tenant must be available with at least one subscription", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", + "training": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Users (or SPs) need the 'Azure Connected Machine Onboarding' or 'Contributor' role to onboarding of servers", - "guid": "33ee7ad6-c6d3-4733-865c-7acbe44bbe60", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "73686af4-6791-4f89-95ad-a43324e13811", + "link": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/QualityCheck", "services": [ - "RBAC", - "Entra", - "Arc" + "Monitor", + "VM", + "SAP" ], "severity": "Medium", - "subcategory": "Requirements", - "text": "Define which users (AAD user/groups) has access to onboard Azure Arc-enabled servers", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Perform a quality check for SAP HANA on the provisioned Azure infrastructure to verify that provisioned VMs comply with SAP HANA on Azure best practices." }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Ensure to only add the rights to users or groups that is required to perform their role", - "guid": "9d79f2e8-7778-4424-a516-775c6fa95b96", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "616785d6-fa96-4c96-ad88-518f482734c8", + "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-zones", "services": [ - "RBAC", - "Entra", - "Arc" + "Subscriptions", + "SAP", + "Monitor" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Use the principle of least privileged", - "waf": "Security" + "severity": "High", + "subcategory": "Monitoring", + "text": "For each Azure subscription, run a latency test on Azure availability zones before zonal deployment to choose low-latency zones for deployment of SAP on Azure.", + "training": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/AvZone-Latency-Test" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "A service principle with the 'Azure Connected Machine Onboarding' role is required for at-scale onboarding of servers, consider more SP's if onboarding is done by different teams/decentralized management", - "guid": "ad88408e-3727-434b-a76b-a28f21459013", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "410adcba-db46-424f-a6c4-05ecde75c52e", + "link": "https://learn.microsoft.com/azure/advisor/advisor-how-to-improve-reliability", "services": [ - "RBAC", - "Entra", - "Arc" + "Monitor", + "Storage", + "ASR" ], "severity": "Medium", - "subcategory": "Security", - "text": "How many Service Principals are needed for onboarding Arc-enabled servers into Azure", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Run the Resiliency Report to ensure that the configuration of the entire provisioned Azure infrastructure (Compute, Database, Networking, Storage, Site Recovery) complies with the configuration defined by Cloud Adaption Framework for Azure.", + "training": "https://learn.microsoft.com/training/paths/azure-well-architected-framework/" }, { - "category": "Identity", - "checklist": "Azure Arc Review", - "description": "Consider assigning the rights for the 'Azure Connected Machine Onboarding' role at the resource group level, to control the resource creation", - "guid": "65d38e53-f9cc-4bd8-9826-6abca264f9a1", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "86ba2802-1459-4114-95e3-9e5309cccd97", + "link": "https://learn.microsoft.com/azure/sentinel/sap/deployment-overview", "services": [ - "RBAC", - "Entra", - "Arc" + "Monitor", + "Sentinel", + "SAP" ], "severity": "Medium", - "subcategory": "Security", - "text": "Limit the rights to onboard Azure Arc-enabled servers to the desired resource groups", - "waf": "Security" + "subcategory": "Monitoring", + "text": "Implement threat protection by using the Microsoft Sentinel solution for SAP. Use this solution to monitor your SAP systems and detect sophisticated threats throughout the business logic and application layers.", + "training": "https://learn.microsoft.com/training/modules/plan-microsoft-sentinel-deployment-sap/?source=recommendations" }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Plan for agent deployments at scale", - "guid": "6ee79d6b-5c2a-4364-a4b6-9bad38aad53c", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment", + "checklist": "Azure Landing Zone Review", + "guid": "579266bc-ca27-45fa-a1ab-fe9d55d04c3c", + "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance", "services": [ - "Arc", - "Monitor" + "Monitor", + "Cost" ], "severity": "Medium", - "subcategory": "Management", - "text": "Define a strategy for agent provisioning", - "waf": "Operations" + "subcategory": "Monitoring", + "text": "Azure tagging can be leveraged to logically group and track resources, automate their deployments, and most importantly, provide visibility on the incurred costs.", + "training": "https://learn.microsoft.com/training/modules/analyze-costs-create-budgets-azure-cost-management/?source=recommendations" }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Use Microsoft Update to ensure that the connected machine agent is always up-to-date", - "guid": "c78e1d76-6673-457c-9496-74c5ed85b859", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#upgrade-the-agent", + "checklist": "Azure Landing Zone Review", + "guid": "04b8e5e5-13cb-4b22-af62-5a8ecfcf0337", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-test-latency?tabs=windows", "services": [ - "Arc", - "Monitor" + "Monitor", + "VM" ], - "severity": "High", - "subcategory": "Management", - "text": "Define a strategy for agent updates", - "waf": "Operations" + "severity": "Low", + "subcategory": "Performance", + "text": "Use inter-VM latency monitoring for latency-sensitive applications." }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Recommendation is to use Azure Policy, or another automation tool like Azure DevOps - important is to avoid configuration drift.", - "guid": "c7733be2-a1a2-47b7-95a9-1be1f388ff39", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-vm-extensions", + "checklist": "Azure Landing Zone Review", + "guid": "07e5ed53-3d96-43d8-87ea-631b77da5aba", + "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide-storage", "services": [ - "Arc", - "AzurePolicy", - "Monitor" + "Monitor", + "SAP", + "ASR" ], "severity": "Medium", - "subcategory": "Management", - "text": "Define a strategy for extension installation", - "waf": "Operations" + "subcategory": "Performance", + "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-storage/?source=recommendations" }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Use automatic upgrades where available and define an update strategy for all extensions not supporting automatic upgrades.", - "guid": "4c2bd463-cbbb-4c86-a195-abb91a4ed90d", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-automatic-vm-extension-upgrade?tabs=azure-portal", + "checklist": "Azure Landing Zone Review", + "guid": "abb6af9c-982c-4cf1-83fb-329fafd1ee56", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", "services": [ - "Arc", - "Monitor" + "SAP", + "Monitor", + "Storage" ], - "severity": "High", - "subcategory": "Management", - "text": "Define a strategy for extension updates", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Performance", + "text": "Exclude all the database file systems and executable programs from antivirus scans. Including them could lead to performance problems. Check with the database vendors for prescriptive details on the exclusion list. For example, Oracle recommends excluding /oracle//sapdata from antivirus scans." }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Azure Automanage help implement Microsoft best-practices for servers management in Azure", - "guid": "7a927c39-74d1-4102-aac6-aae01e6a84de", - "link": "https://learn.microsoft.com/azure/automanage/automanage-arc", + "checklist": "Azure Landing Zone Review", + "guid": "c027f893-f404-41a9-b33d-39d625a14964", + "link": "https://sapit-forme-prod.authentication.eu11.hana.ondemand.com/login", "services": [ - "Arc", - "Monitor" + "Monitor", + "SAP" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Consider using Azure Automanage to control settings and avoid configuration drift on servers", - "waf": "Operations" + "severity": "Low", + "subcategory": "Performance", + "text": "Consider collecting full database statistics for non-HANA databases after migration. For example, implement SAP note 1020260 - Delivery of Oracle statistics." }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "37b6b780-cbaf-4e6c-9658-9d457a927c39", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", + "checklist": "Azure Landing Zone Review", + "guid": "fdafb1f5-3eee-4354-a8c9-deb8127ebc2e", + "link": "https://learn.microsoft.com/azure/virtual-machines/workloads/oracle/configure-oracle-asm", "services": [ - "Arc", - "Monitor" + "SAP", + "Monitor", + "Storage" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Monitor for unresponsive agents", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Performance", + "text": "Consider using Oracle Automatic Storage Management (ASM) for all Oracle deployments that use SAP on Azure.", + "training": "https://learn.microsoft.com/training/paths/administer-infrastructure-resources-in-azure/?source=recommendations" }, { "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "74d1102c-ac6a-4ae0-8e6a-84de5df47d2d", - "link": "https://learn.microsoft.com/azure/azure-monitor/agents/log-analytics-agent#data-collected", + "checklist": "Azure Landing Zone Review", + "guid": "33c5d5bf-daf3-4f0d-bd50-6010fdcec22e", + "link": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/announcement-sap-on-azure-oracle-performance-efficiency-scripts/ba-p/3725178", "services": [ - "Arc", - "Monitor" + "SQL", + "Monitor", + "SAP" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Design a monitoring strategy to send metrics and logs to an Log Analytics workspace", - "waf": "Operations" + "subcategory": "Performance", + "text": "For SAP on Azure running Oracle, a collection of SQL scripts can help you diagnose performance problems. Automatic Workload Repository (AWR) reports contain valuable information for diagnosing problems in the Oracle system. We recommend that you run an AWR report during several sessions and choose peak times for it, to ensure broad coverage for the analysis.", + "training": "https://learn.microsoft.com/ja-jp/azure/well-architected/oracle-iaas/performance-efficiency" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "92881b1c-d5d1-4e54-a296-59e3958fd782", - "link": "https://learn.microsoft.com/azure/service-health/resource-health-alert-monitor-guide", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5ba34d46-85e2-4213-ace7-bb122f7c95f0", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "services": [ - "Arc", - "Monitor" + "WAF", + "AppGW", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use notification in Activity logs to receive notification on unexpected changes to the resources", - "waf": "Operations" + "subcategory": "App delivery", + "text": "For secure delivery of HTTP/S apps, use Application Gateway v2 and ensure that WAF protection and policies are enabled.", + "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "89c93555-6d02-4bfe-9564-b0d834a34872", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/learn/tutorial-enable-vm-insights", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "fa9d30bc-1b82-4e4b-bfdf-6b017938b9e6", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", "services": [ - "Arc", - "Monitor" + "VM", + "SAP", + "DNS" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor for compliance and operational monitoring", - "waf": "Operations" + "subcategory": "DNS", + "text": "If the virtual machine's DNS or virtual name is not changed during migration to Azure, Background DNS and virtual names connect many system interfaces in the SAP landscape, and customers are only sometimes aware of the interfaces that developers define over time. Connection challenges arise between various systems when virtual or DNS names change after migrations, and it's recommended to retain DNS aliases to prevent these types of difficulties.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "guid": "5df47d2d-9288-41b1-ad5d-1e54a29659e3", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "a2858f78-105b-4f52-b7a9-5b0f4439743b", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", "services": [ - "Arc", - "Monitor" + "SAP", + "DNS", + "VNet" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Create an alert to identify Azure Arc-enabled servers that aren't using the latest version of the Azure connected machine agent", - "waf": "Operations" + "subcategory": "DNS", + "text": "Use different DNS zones to distinguish each environment (sandbox, development, preproduction, and production) from each other. The exception is for SAP deployments with their own VNet; here, private DNS zones might not be necessary.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" }, { - "category": "Management and Monitoring", - "checklist": "Azure Arc Review", - "description": "Use Update Management in Azure Automation or the new Update Management Center (preview) functionality to ensure update management of servers", - "guid": "ae2cc84c-37b6-4b78-8cba-fe6c46589d45", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/hybrid/server/best-practices/arc-update-management", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "a3592829-e6e2-4061-9368-6af46791f893", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", "services": [ - "Arc", - "Monitor" + "SAP", + "VNet", + "ACR" ], - "severity": "Low", - "subcategory": "Security", - "text": "Use Azure Arc-enabled servers to control software updates deployments to servers", - "waf": "Operations" + "severity": "Medium", + "subcategory": "Hybrid", + "text": "Local and global VNet peering provide connectivity and are the preferred approaches to ensure connectivity between landing zones for SAP deployments across multiple Azure regions", + "training": "https://learn.microsoft.com/training/modules/configure-vnet-peering/?source=recommendations" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "The Connected Machine Agent will by default communicate with Azure services over public Internet connectivity using HTTPS (TCP port 443)", - "guid": "f6e043d2-aa35-4927-88e6-e2050725769e", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#details", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "41742694-3ff8-4ae7-b7d4-743176c8bcbf", + "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide", "services": [ - "Arc" + "NVA", + "SAP" ], "severity": "High", - "subcategory": "Networking", - "text": "Define a connectivity method from the server to Azure", - "waf": "Operations" + "subcategory": "Hybrid", + "text": "It is not supported to deploy any NVA between SAP application and SAP Database server", + "training": "https://me.sap.com/notes/2731110" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "The Connected Machine Agent can be configured to use a proxy server, it is recommended to define the proxy server address using 'azcmagent config set proxy.url' command on the local system.", - "guid": "46691e88-35ac-4932-823e-13800523081a", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#update-or-remove-proxy-settings", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "7d4bc7d2-c34a-452e-8f1d-6ae3c8eafcc3", + "link": "https://learn.microsoft.com/training/modules/introduction-azure-virtual-wan/?source=recommendations", "services": [ - "Arc" + "VWAN", + "SAP", + "ACR" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Is a proxy server a required for communication over the Public Internet", - "waf": "Operations" + "subcategory": "Hybrid", + "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", + "training": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "The Connected Machine Agent can use a Private Link for communication with Azure Services over an existing ExpressRoute or VPN connection", - "guid": "94174158-33ee-47ad-9c6d-3733165c7acb", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/private-link-security", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "0cedb1f6-ae6c-492b-8b17-8061f50b16d3", + "link": "https://learn.microsoft.com/azure/well-architected/services/networking/network-virtual-appliances/reliability", "services": [ - "PrivateLink", - "ExpressRoute", - "Arc", - "VPN" + "NVA", + "VNet" ], "severity": "Medium", - "subcategory": "Networking", - "text": "Is a private (not public Internet) connection required?", - "waf": "Operations" - }, - { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "Firewall configuration might be required for the agent to communicate with Azure, use the link to see ServiceTags and/or URL's required", - "guid": "e44bbe60-9d79-4f2e-a777-8424c516775c", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#service-tags", - "services": [ - "Arc" - ], - "severity": "High", - "subcategory": "Networking", - "text": "Will Firewall configurations be needed in order to ensure communication with Azure Services?", - "waf": "Security" + "subcategory": "Hybrid", + "text": "Consider deploying network virtual appliances (NVAs) between regions only if partner NVAs are used. NVAs between regions or VNets aren't required if native NVAs are present. When you're deploying partner networking technologies and NVAs, follow the vendor's guidance to verify conflicting configurations with Azure networking.", + "training": "https://learn.microsoft.com/training/modules/control-network-traffic-flow-with-routes/?source=recommendations" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "Use available automation tool for the system in question to regularly update the Azure endpoints", - "guid": "6fa95b96-ad88-4408-b372-734b876ba28f", - "link": "https://www.microsoft.com/download/details.aspx?id=56519", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "facc08c6-ea95-4641-91cd-fa09e573adbd", + "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", "services": [ - "Arc" + "NVA", + "VWAN", + "SAP", + "VNet" ], - "severity": "Low", - "subcategory": "Networking", - "text": "Can the Firewall or Proxy rules be automated updated if Service Tags or IP addresses change", - "waf": "Security" + "severity": "Medium", + "subcategory": "Hybrid", + "text": "Virtual WAN manages connectivity between spoke VNets for virtual-WAN-based topologies (no need to set up user-defined routing [UDR] or NVAs), and maximum network throughput for VNet-to-VNet traffic in the same virtual hub is 50 gigabits per second. If necessary, SAP landing zones can use VNet peering to connect to other landing zones and overcome this bandwidth limitation.", + "training": "https://learn.microsoft.com/training/modules/hub-and-spoke-network-architecture/?source=recommendations" }, { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "Configure Servers to use Transport Layer Security (TLS) version 1.2", - "guid": "21459013-65d3-48e5-9f9c-cbd868266abc", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#transport-layer-security-12-protocol", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "82734c88-6ba2-4802-8459-11475e39e530", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "Arc" + "VNet", + "VM", + "SAP" ], "severity": "High", - "subcategory": "Networking", - "text": "Always use secure communication for Azure where possible", - "waf": "Security" - }, - { - "category": "Networking", - "checklist": "Azure Arc Review", - "description": "All extensions (like log analytics etc.) have separate network requirements, be sure to include all in the network design.", - "guid": "a264f9a1-9bf3-49d9-9d44-c7c8919ca1f6", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/hybrid/arc-enabled-servers/eslz-arc-servers-connectivity#define-extensions-connectivity-method", - "services": [ - "PrivateLink", - "Arc", - "Monitor" - ], - "severity": "Low", - "subcategory": "Networking", - "text": "Include communication for Azure Arc-enabled Servers extensions in the design (firewall/proxy/private link)", - "waf": "Security" + "subcategory": "IP plan", + "text": "Public I.P assignment to VM running SAP Workload is not recommended.", + "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "ac6aae01-e6a8-44de-9df4-7d2d92881b1c", - "link": "https://learn.microsoft.com/azure/governance/policy/", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "9cccd979-366b-4cda-8750-ab1ab039d95d", + "link": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations", "services": [ - "Arc", - "AzurePolicy" + "VNet", + "ASR" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Use Azure Policy to implement a governance model for hybrid connected servers", - "waf": "Security" + "severity": "High", + "subcategory": "IP plan", + "text": "Consider reserving I.P address on DR side when configuring ASR", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "5c2a3649-4b69-4bad-98aa-d53cc78e1d76", - "link": "https://learn.microsoft.com/azure/governance/machine-configuration/overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "54c7c892-9cb1-407d-9325-ae525ba34d46", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "services": [ - "Arc" + "VNet" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Consider using Machine configurations for in guest OS configurations", - "waf": "Operations" + "severity": "High", + "subcategory": "IP plan", + "text": "Avoid using overlapping IP address ranges for production and DR sites.", + "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "667357c4-4967-44c5-bd85-b859c7733be2", - "link": "https://learn.microsoft.com/azure/governance/machine-configuration/machine-configuration-create", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "6e154e3a-a359-4282-ae6e-206173686af4", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-delegate-subnet", "services": [ - "Arc", - "AzurePolicy" + "Storage", + "VNet" ], "severity": "Medium", - "subcategory": "Management", - "text": "Evaluate the need for custom Guest Configuration policies", - "waf": "Operations" + "subcategory": "IP plan", + "text": "While Azure does help you to create multiple delegated subnets in a VNet, only one delegated subnet can exist in a VNet for Azure NetApp Files. Attempts to create a new volume will fail if you use more than one delegated subnet for Azure NetApp Files.", + "training": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-network-topologies?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "49674c5e-d85b-4859-a773-3be2a1a27b77", - "link": "https://learn.microsoft.com/azure/automation/change-tracking/overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d8a03e97-7784-424d-9167-85d6fa96c96a", + "link": "https://learn.microsoft.com/azure/well-architected/services/networking/azure-firewall?toc=%2Fazure%2Ffirewall%2Ftoc.json&bc=%2Fazure%2Ffirewall%2Fbreadcrumb%2Ftoc.json", "services": [ - "Arc", - "Monitor" + "Firewall" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Consider using change tracking for tracking changes made on the servers", - "waf": "Operations" + "subcategory": "Internet", + "text": "Use Azure Firewall to govern Azure outbound traffic to the internet, non-HTTP/S inbound connections, and East/West traffic filtering (if the organization requires it)", + "training": "https://learn.microsoft.com/training/paths/secure-networking-infrastructure/" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "d5d1e54a-2965-49e3-a58f-d78289c93555", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/data-residency", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d88518f4-8273-44c8-a6ba-280214591147", "services": [ - "Arc" + "SAP", + "AppGW" ], "severity": "Medium", - "subcategory": "Requirements", - "text": "Make sure to use an Azure region for storing the metadata approved by the organization", - "waf": "Security" + "subcategory": "Internet", + "text": "Use SAP Web dispatcher or third party service like NetScaler in conjunction with Application gateway if necessary to overcome reverse proxy limitation for SAP web Apps." }, - { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "195abb91-a4ed-490d-ae2c-c84c37b6b780", - "link": "https://learn.microsoft.com/azure/key-vault/general/basic-concepts", + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5e39e530-9ccc-4d97-a366-bcda2750ab1a", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "Arc", - "AKV" + "WAF", + "ACR", + "FrontDoor", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Use Azure Key Vault for certificate management on servers", - "waf": "Security" + "subcategory": "Internet", + "text": "Use Azure Front Door and WAF policies to provide global protection across Azure regions for inbound HTTP/S connections to a landing zone.", + "training": "https://learn.microsoft.com/training/paths/secure-application-delivery/" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Consider using a short-lived Azure AD service principal client secrets.", - "guid": "6d02bfe4-564b-40d8-94a3-48726ee79d6b", - "link": "https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "b039d95d-54c7-4c89-89cb-107d5325ae52", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "services": [ - "Entra", - "Arc", - "Storage", - "AKV" + "AzurePolicy", + "WAF", + "FrontDoor", + "AppGW" ], - "severity": "High", - "subcategory": "Secrets", - "text": "What is the acceptable life time of the secret used by SP's", - "waf": "Security" + "severity": "Medium", + "subcategory": "Internet", + "text": "Take advantage of Web Application Firewall policies in Azure Front Door when you're using Azure Front Door and Application Gateway to protect HTTP/S applications. Lock down Application Gateway to receive traffic only from Azure Front Door.", + "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "A private key is saved to the disk, ensure this is protected using disk encryption", - "guid": "a1a27b77-5a91-4be1-b388-ff394c2bd463", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#using-disk-encryption", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5ada4332-4e13-4811-9231-81aa41742694", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "services": [ - "Arc", - "AKV" + "LoadBalancer", + "WAF", + "AppGW" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Secure the public key for Azure Arc-enabled Servers", - "waf": "Security" + "subcategory": "Internet", + "text": "Use a web application firewall to scan your traffic when it's exposed to the internet. Another option is to use it with your load balancer or with resources that have built-in firewall capabilities like Application Gateway or third-party solutions.", + "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Local administrator is required to install the Connected Machine Agent on Windows and Linux systems", - "guid": "29659e39-58fd-4782-a9c9-35556d02bfe4", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-portal#install-manually", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e73de7d5-6f36-4217-a526-e1a621ecddde", + "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", "services": [ - "Arc" + "VWAN", + "SAP", + "ACR" ], - "severity": "High", - "subcategory": "Security", - "text": "Ensure there is local administrator access for executing the agent installation", - "waf": "Security" + "severity": "Medium", + "subcategory": "Internet", + "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", + "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/10-explore-azure-front-door" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Members of the local administrator group on Windows and users with root privileges on Linux, have permissions to manage the agent via command line.", - "guid": "564b0d83-4a34-4872-9ee7-9d6b5c2a3649", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#agent-security-and-permissions", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "3c536a3e-1b6b-4e87-95ca-15edb47251c0", + "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "services": [ - "Arc" + "Storage", + "VNet", + "Backup", + "PrivateLink", + "ACR" ], "severity": "Medium", - "subcategory": "Security", - "text": "Limit the amount of users with local administrator rights to the servers", - "waf": "Security" + "subcategory": "Internet", + "text": "To prevent data leakage, use Azure Private Link to securely access platform as a service resources like Azure Blob Storage, Azure Files, Azure Data Lake Storage Gen2, Azure Data Factory, and more. Azure Private Endpoint can also help to secure traffic between VNets and services like Azure Storage, Azure Backup, and more. Traffic between your VNet and the Private Endpoint enabled service travels across the Microsoft global network, which prevents its exposure to the public internet.", + "training": "https://learn.microsoft.com/training/modules/design-implement-private-access-to-azure-services/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "4b69bad3-8aad-453c-a78e-1d76667357c4", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", "services": [ - "Entra", - "Arc" + "VM", + "SAP" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Consider using and restricting access to managed identities for applications.", - "waf": "Security" + "severity": "High", + "subcategory": "Segmentation", + "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", + "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "description": "Use Defender for Endpoint or another AV and EDR solution to protect endpoints", - "guid": "5a91be1f-388f-4f39-9c2b-d463cbbbc868", - "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "3ff8ae7d-7d47-4431-96c8-bcbf45bbe609", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-multivip-overview", "services": [ - "Arc", - "Defender" + "LoadBalancer" ], "severity": "Medium", - "subcategory": "Security", - "text": "Enable Defender for Servers for all servers to secure hybrid workloads from threats", - "waf": "Security" + "subcategory": "Segmentation", + "text": "Make sure that internal deployments for Azure Load Balancer are set up to use Direct Server Return (DSR). This setting will reduce latency when internal load balancer configurations are used for high-availability configurations on the DBMS layer.", + "training": "https://learn.microsoft.com/ja-jp/training/modules/load-balancing-non-https-traffic-azure/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "cbafe6c4-6589-4d45-9a92-7c3974d1102c", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "6791f893-5ada-4433-84e1-3811523181aa", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "services": [ - "Arc" + "SAP", + "VM", + "VNet" ], "severity": "Medium", - "subcategory": "Security", - "text": "Define controls to detect security misconfigurations and track compliance", - "waf": "Security" + "subcategory": "Segmentation", + "text": "You can use application security group (ASG) and NSG rules to define network security access-control lists between the SAP application and DBMS layers. ASGs group virtual machines to help manage their security.", + "training": "https://learn.microsoft.com/training/modules/configure-network-security-groups/?source=recommendations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Arc Review", - "guid": "cbbbc868-195a-4bb9-8a4e-d90dae2cc84c", - "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#extension-allowlists-and-blocklists", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "45bbe609-d8a0-43e9-9778-424d616785d6", + "link": "https://me.sap.com/notes/2015553", "services": [ - "Arc" + "SAP", + "VNet" ], - "severity": "Medium", - "subcategory": "Security", - "text": "Use allow- or block-lists to control what extensions can be installed on the Azure Arc-enabled servers", - "waf": "Security" + "severity": "High", + "subcategory": "Segmentation", + "text": "Placing of the SAP application layer and SAP DBMS in different Azure VNets that aren't peered isn't supported.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "aff6691b-4935-4ada-9222-3ece81b12318", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", + "guid": "fa96c96a-d885-418f-9827-34c886ba2802", + "link": "https://learn.microsoft.com/azure/sap/workloads/proximity-placement-scenarios", "services": [ - "ASR" + "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Do not combine ASCS and Database cluster on to single/same VM" + "subcategory": "Segmentation", + "text": "For optimal network latency with SAP applications, consider using Azure proximity placement groups.", + "training": "https://learn.microsoft.com/azure/virtual-machines/co-location#planned-maintenance-and-proximity-placement-groups" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "1a541741-5833-4fb4-ae3c-2df743165c3a", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", + "guid": "18c8b61c-855a-4405-b6ed-266455e4f4ce", + "link": "https://me.sap.com/notes/2015553", "services": [ - "ASR", - "LoadBalancer" + "SAP" ], - "severity": "Medium", - "subcategory": " ", - "text": "Make sure the Floating IP is enabled on the Load balancer" + "severity": "High", + "subcategory": "Segmentation", + "text": "It is NOT supported at all to run an SAP Application Server layer and DBMS layer split between on-premise and Azure. Both layers need to completely reside either on-premise or in Azure.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "cbe05bbe-209d-4490-ba47-778424d11678", - "link": "https://learn.microsoft.com/azure/security-center/", + "guid": "b65c878b-4b14-4f4e-92d8-d873936493f2", + "link": "https://me.sap.com/notes/2015553", "services": [ - "VM", - "RBAC", - "Entra", - "ASR" + "SAP", + "VNet", + "Cost" ], - "severity": "Medium", - "subcategory": " ", - "text": "Do not mix servers of different roles in the same availability set. Keep central services VMs, database VMs, application VMs in their own availability sets" + "severity": "High", + "subcategory": "Segmentation", + "text": "It isn't recommended to host the database management system (DBMS) and application layers of SAP systems in different VNets and connect them with VNet peering because of the substantial costs that excessive network traffic between the layers can produce. Recommend using subnets within the Azure virtual network to separate the SAP application layer and DBMS layer.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "5d2fa56c-56ad-4484-88fe-72734c486ba2", - "link": "https://learn.microsoft.com/azure/security-center/", + "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", "services": [ - "ASR", - "ACR", + "VM", "SAP" ], - "severity": "Medium", - "subcategory": " ", - "text": "Use one proximity placement group per SAP SID. Groups don't span across Availability Zones or Azure regions" + "severity": "High", + "subcategory": "Segmentation", + "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", + "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "80dc0591-cf65-4de8-b130-9cccd579266b", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "guid": "402a9846-d515-4061-aff8-cd30088693fa", + "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel", "services": [ - "VM", - "ASR", - "Entra" + "LoadBalancer" ], - "severity": "Medium", - "subcategory": " ", - "text": "Azure doesn't currently support combining ASCS and db HA in the same Linux Pacemaker cluster; separate them into individual clusters. However, you can combine up to five multiple central-services clusters into a pair of VMs." + "severity": "High", + "subcategory": "Segmentation", + "text": "If using Load Balancer with Linux guest operating systems, check that the Linux network parameter net.ipv4.tcp_timestamps is set to 0.", + "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Network Topology and Connectivity", "checklist": "Azure Landing Zone Review", - "guid": "cca275fa-a1ab-4fe9-b55d-04c3c4919cb1", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "guid": "87585797-5551-4d53-bb7d-a94ee415734d", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration", "services": [ - "ASR", - "LoadBalancer" + "SAP", + "VNet" ], "severity": "Medium", - "subcategory": " ", - "text": "Use a Standard Load Balancer SKU in front of ASCS and DB clusters" + "subcategory": "Segmentation", + "text": "For SAP RISE/ECS deployments, virtual peering is the preferred way to establish connectivity with customer’s existing Azure environment. Both the SAP vnet and customer vnet(s) are protected with network security groups (NSG), enabling communication on SAP and database ports through the vnet peering" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "b3d1325a-e124-4ba3-9df6-85eddce9bd3b", - "link": "https://www.microsoft.com/itshowcase/implementing-a-zero-trust-security-model-at-microsoft", + "guid": "209d490d-a477-4784-84d1-16785d2fa56c", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "VM", - "ASR", - "Storage" + "Subscriptions", + "RBAC", + "SAP" ], - "severity": "Medium", - "subcategory": " ", - "text": "Both VMs in the HA pair should be deployed in an availability set, or Availability Zones should be the same size and have the same storage configuration" + "severity": "High", + "subcategory": "Governance", + "text": "Customize role-based access control (RBAC) roles for SAP on Azure spoke subscriptions to avoid accidental network-related changes" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "b0cdb3b5-5eb2-4ec1-9eea-a3592829e2ed", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "guid": "56ad4840-8fe7-4273-9c48-6ba280dc0591", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "ASR" + "NVA", + "SAP", + "PrivateLink" ], "severity": "Medium", - "subcategory": " ", - "text": "Native database replication technology should be used to synchronize the database in a HA pair." + "subcategory": "Governance", + "text": "Isolate DMZs and NVAs from the rest of the SAP estate, configure Azure Private Link, and securely manage and control the SAP on Azure resources" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "b2173676-aff6-4691-a493-5ada42223ece", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "guid": "cf65de8e-1309-4ccc-b579-266bcca275fa", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "ASR", + "SQL", + "Storage", + "Backup", "SAP" ], "severity": "Medium", - "subcategory": " ", - "text": "Perform a point-in-time recovery for your production databases at any point and in a time frame that meets your RTO; point-in-time recovery typically includes operator errors deleting data either on the DBMS layer or through SAP, incidentally" + "subcategory": "Governance", + "text": "For SAP database server encryption, use the SAP HANA native encryption technology. If you're using Azure SQL Database, use Transparent Data Encryption (TDE) offered by the DBMS provider to secure your data and log files, and ensure the backups are also encrypted." }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "81b12318-1a54-4174-8583-3fb4ae3c2df7", + "guid": "a1abfe9d-55d0-44c3-a491-9cb1b3d1325a", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", "services": [ - "VNet", - "ASR" + "Storage" ], "severity": "Medium", - "subcategory": " ", - "text": "The CIDR for the primary virtual network (VNet) shouldn't conflict or overlap with the CIDR of the DR site's Vnet" + "subcategory": "Governance", + "text": "Azure Storage encryption is enabled by default" }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "43165c3a-cbe0-45bb-b209-d490da477784", - "services": [ - "VM", - "ASR", - "Entra" - ], + "guid": "e124ba34-df68-45ed-bce9-bd3bb0cdb3b5", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [], "severity": "Medium", - "subcategory": " ", - "text": "Use Site Recovery to replicate an application server to a DR site. Site Recovery can also help with replicating central-services cluster VMs to the DR site. When you invoke DR, you'll need to reconfigure the Linux Pacemaker cluster on the DR site (for example, replace the VIP or SBD, run corosync.conf, and more)." + "subcategory": "Governance", + "text": " " }, { - "category": "Business Continuity and Disaster Recovery", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "24d11678-5d2f-4a56-a56a-d48408fe7273", - "services": [ - "ASR" - ], + "guid": "5eb2ec14-eeaa-4359-8829-e2edb2173676", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [], "severity": "Medium", - "subcategory": " ", - "text": "Native database replication should be used to synchronize data to the DR site, rather than Azure Site Recovery" + "subcategory": "Governance", + "text": " " }, { - "category": "Compute", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "2829e2ed-b217-4367-9aff-6691b4935ada", + "guid": "ce9bd3bb-0cdb-43b5-9eb2-ec14eeaa3592", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "services": [ - "VM" + "AKV" ], - "severity": "Medium", - "subcategory": " ", - "text": "Make quota requests for correct VM SKU and Zones" + "severity": "High", + "subcategory": "Secrets", + "text": "Use Azure Key Vault to store your secrets and credentials" }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", - "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", + "guid": "829e2edb-2173-4676-aff6-691b4935ada4", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "services": [ - "Subscriptions", - "RBAC", - "Entra" + "AKV" ], - "severity": "High", - "subcategory": "Identity", - "text": "Enforce a RBAC model for management groups, subscriptions, resource groups and resources", - "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" + "severity": "Medium", + "subcategory": "Secrets", + "text": "It is recommended to LOCK the Azure Resources post successful deployment to safeguard against unauthorized changes" }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "45911475-e39e-4530-accc-d979366bcda2", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "guid": "2223ece8-1b12-4318-8a54-17415833fb4a", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "AKV", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Enforce Principle propagation for forwarding the identity from SAP cloud application to SAP on-premises (Including IaaS) through cloud connector", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" + "subcategory": "Secrets", + "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "guid": "e3c2df74-3165-4c3a-abe0-5bbe209d490d", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "RBAC", + "AKV", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP SaaS applications like SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics and SAP C4C with Azure AD using SAML." + "subcategory": "Secrets", + "text": "Based on existing requirements, regulatory and compliance controls (internal/external) - Determine what Azure Policies and Azure RBAC role are needed" }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "guid": "a4777842-4d11-4678-9d2f-a56c56ad4840", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "Defender", + "AKV", + "SAP", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "subcategory": "Secrets", + "text": "When you enable Microsoft Defender for Cloud Standard for SAP, make sure to exclude the SAP database servers from any policy that installs endpoint protection." }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "9eb54dad-7861-4e1c-973a-f3bb003fc9c1", + "guid": "8fe72734-c486-4ba2-a0dc-0591cf65de8e", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "RBAC", + "SAP", + "AKV" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP NetWeaver-based web applications like SAP Fiori and SAP Web GUI by using SAML.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" + "subcategory": "Secrets", + "text": "Delegate an SAP admin custom role with just-in-time access." }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "guid": "1309cccd-5792-466b-aca2-75faa1abfe9d", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", + "AKV", "SAP" ], "severity": "Medium", - "subcategory": "Identity", - "text": "You can implement SSO to SAP GUI by using SAP NetWeaver SSO or a partner solution.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "subcategory": "Secrets", + "text": "encrypt data in transit by integrating the third-party security product with secure network communications (SNC) for DIAG (SAP GUI), RFC, and SPNEGO for HTTPS" }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "23181aa4-1742-4694-9ff8-ae7d7d474317", + "guid": "55d04c3c-4919-4cb1-a3d1-325ae124ba34", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", + "AKV", "SAP", - "AKV" + "Entra" ], "severity": "Medium", - "subcategory": "Identity", - "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution.", - "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" + "subcategory": "Secrets", + "text": "Azure Active Directory (Azure AD) with SAML 2.0 can also provide SSO to a range of SAP applications and platforms like SAP NetWeaver, SAP HANA, and the SAP Cloud Platform" }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "6c8bcbf4-5bbe-4609-b8a0-3e97778424d6", - "link": "https://blogs.sap.com/2017/07/12/sap-single-sign-on-protect-your-sap-landscape-with-x.509-certificates/", + "guid": "df685edd-ce9b-4d3b-a0cd-b3b55eb2ec14", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP", - "AKV" + "AKV", + "SAP" ], "severity": "Medium", - "subcategory": "Identity", - "text": "For SSO for SAP GUI and web browser access, implement SNC – Kerberos/SPNEGO (simple and protected GSSAPI negotiation mechanism) due to its ease of configuration and maintenance. For SSO with X.509 client certificates, consider the SAP Secure Login Server, which is a component of the SAP SSO solution." + "subcategory": "Secrets", + "text": "Make sure you harden the operating system to eradicate vulnerabilities that could lead to attacks on the SAP database." }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", + "guid": "eeaa3592-829e-42ed-a217-3676aff6691b", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "AKV" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO by using OAuth for SAP NetWeaver to allow third-party or custom applications to access SAP NetWeaver OData services." + "subcategory": "Secrets", + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "a747c350-8d4c-449c-93af-393dbca77c48", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", + "guid": "4935ada4-2223-4ece-a1b1-23181a541741", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "AKV" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP HANA" + "subcategory": "Secrets", + "text": "Use an Azure Key Vault per application per environment per region." }, { - "category": "Identity and Access", + "category": "Security, Governance and Compliance", "checklist": "Azure Landing Zone Review", - "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", - "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", + "guid": "5833fb4a-e3c2-4df7-9316-5c3acbe05bbe", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "services": [ - "Entra", - "SAP" + "AKV" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Consider Azure AD an identity provider for SAP systems hosted on RISE. For more information, see Integrating the Service with Azure AD." + "subcategory": "Secrets", + "text": " " }, { - "category": "Identity and Access", + "category": "Storage", "checklist": "Azure Landing Zone Review", - "guid": "e4e48226-ce54-44b6-bb6b-bfa15bd8f753", - "link": "https://github.com/azuredevcollege/SAP/blob/master/sap-oauth-saml-flow/README.md", + "guid": "d579266b-cca2-475f-aa1a-bfe9d55d04c3", "services": [ - "Entra", - "SAP" + "SQL", + "Storage" ], "severity": "Medium", - "subcategory": "Identity", - "text": "For applications that access SAP, you might want to use principal propagation to establish SSO." + "subcategory": " ", + "text": "Disk config for Oracle, SQL, HANA" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "Azure Service Bus Premium provides encryption of data at rest. If you use your own key, the data is still encrypted using the Microsoft-managed key, but in addition the Microsoft-managed key will be encrypted using the customer-managed key. ", + "guid": "87af4a79-1f89-439b-ba47-768e14c11567", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/configure-customer-managed-key", "services": [ - "Entra", - "SAP" + "ServiceBus" ], - "severity": "Medium", - "subcategory": "Identity", - "text": "If you're using SAP BTP services or SaaS solutions that require SAP Identity Authentication Service (IAS), consider implementing SSO between SAP Cloud Identity Authentication Services and Azure AD to access those SAP services. This integration lets SAP IAS act as a proxy identity provider and forwards authentication requests to Azure AD as the central user store and identity provider." + "severity": "Low", + "subcategory": "Data Protection", + "text": "Use customer-managed key option in data at rest encryption when required", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "Communication between a client application and an Azure Service Bus namespace is encrypted using Transport Layer Security (TLS). Azure Service Bus namespaces permit clients to send and receive data with TLS 1.0 and above. To enforce stricter security measures, you can configure your Service Bus namespace to require that clients send and receive data with a newer version of TLS.", + "guid": "5c1ea55b-46a9-448f-b8ae-7d7e4b475b6c", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/transport-layer-security-enforce-minimum-version", "services": [ - "Entra", - "SAP" + "ServiceBus" ], "severity": "Medium", - "subcategory": "Identity", - "text": "Implement SSO to SAP BTP" + "subcategory": "Data Protection", + "text": "Enforce a minimum required version of Transport Layer Security (TLS) for requests ", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "01f11b7f-38df-4251-9c76-4dec19abd3e8", - "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-successfactors-inbound-provisioning-cloud-only-tutorial", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "When you create a Service Bus namespace, a SAS rule named RootManageSharedAccessKey is automatically created for the namespace. This policy has Manage permissions for the entire namespace. It's recommended that you treat this rule like an administrative root account and don't use it in your application. Using AAD as an authentication provider with RBAC is recommended. ", + "guid": "8bcbf59b-ce65-4de8-a03f-97879468d66a", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-sas#shared-access-authorization-policies", "services": [ + "AzurePolicy", + "TrafficManager", "Entra", - "SAP" + "ServiceBus", + "RBAC" ], "severity": "Medium", - "subcategory": "Identity", - "text": "If you're using SAP SuccessFactors, consider using the Azure AD automated user provisioning. With this integration, as you add new employees to SAP SuccessFactors, you can automatically create their user accounts in Azure AD. Optionally, you can create user accounts in Microsoft 365 or other SaaS applications that are supported by Azure AD. Use write-back of the email address to SAP SuccessFactors." + "subcategory": "Identity and Access Management", + "text": "Avoid using root account when it is not necessary", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "A Service Bus client app running inside an Azure App Service application or in a virtual machine with enabled managed entities for Azure resources support does not need to handle SAS rules and keys, or any other access tokens. The client app only needs the endpoint address of the Service Bus Messaging namespace. ", + "guid": "786d60f9-6c96-4ad8-a55d-04c2b39c986b", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-managed-service-identity", "services": [ - "Subscriptions", - "AzurePolicy", - "SAP" + "AKV", + "Storage", + "VM", + "AppSvc", + "Entra", + "ServiceBus" ], "severity": "Medium", - "subcategory": "Subscriptions", - "text": "enforce existing Management Group policies to SAP Subscriptions", - "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" + "subcategory": "Identity and Access Management", + "text": "When possible, your application should be using a managed identity to authenticate to Azure Service Bus. If not, consider having the storage credential (SAS, service principal credential) in Azure Key Vault or an equivalent service", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "When creating permissions, provide fine-grained control over a client's access to Azure Service Bus. Permissions in Azure Service Bus can and should be scoped to the individual resource level e.g. queue, topic or subscription. ", + "guid": "f615658d-e558-4f93-9249-b831112dbd7e", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/authenticate-application#azure-built-in-roles-for-azure-service-bus", "services": [ + "Storage", + "Entra", "Subscriptions", - "SAP" + "ServiceBus", + "RBAC" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Integrate tightly coupled applications into the same SAP subscription to avoid additional routing and management complexity", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" + "subcategory": "Identity and Access Management", + "text": "Use least privilege data plane RBAC", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "Azure Service Bus resource logs include operational logs, virtual network and IP filtering logs. Runtime audit logs capture aggregated diagnostic information for various data plane access operations (such as send or receive messages) in Service Bus.", + "guid": "af12e7f9-43f6-4304-922d-929c2b1cd622", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/monitor-service-bus-reference", "services": [ - "Subscriptions" + "Monitor", + "VNet", + "ServiceBus" ], - "severity": "High", - "subcategory": "Subscriptions", - "text": "Leverage Subscription as scale unit and scaling our resources, consider deploying subscription per environment eg. Sandbox, non-prod, prod ", - "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Enable logging for security investigation. Use Azure Monitor to trace resource logs and runtime audit logs (currently available only in the premium tier)", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "Azure Service Bus by default has a public IP address and is Internet-reachable. Private endpoints allow traffic between your virtual network and Azure Service Bus traverses over the Microsoft backbone network. In addition to that, you should disable public endpoints if those are not used. ", + "guid": "9ae669ca-48e4-4a85-b222-3ece8bb12307", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/private-link-service", "services": [ - "VM", - "Subscriptions" + "VNet", + "ServiceBus", + "PrivateLink" ], - "severity": "High", - "subcategory": "Subscriptions", - "text": "Ensure quota increase as a part of subscription provisioning (e.g. total available VM cores within a subscription)", - "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" + "severity": "Medium", + "subcategory": "Networking", + "text": "Consider using private endpoints to access Azure Service Bus and disable public network access when applicable.", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", - "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", + "category": "Security", + "checklist": "Azure Service Bus Review", + "description": "With IP firewall, you can restrict the public endpoint further to only a set of IPv4 addresses or IPv4 address ranges in CIDR (Classless Inter-Domain Routing) notation. ", + "guid": "ca5f06f1-58e3-4ea3-a92c-2de7e2165c3a", + "link": "https://learn.microsoft.com/azure/service-bus-messaging/service-bus-ip-filtering", "services": [ - "Subscriptions" + "ServiceBus" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Consider only allowing access to Azure Service Bus namespace from specific IP addresses or ranges", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + }, + { + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Automatic instance repairs ensure that unhealthy instances are promptly identified and replaced, maintaining a set of healthy instances within your scale set.", + "guid": "7e13c105-675c-41e9-95b4-59837ff7ae7c", + "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-automatic-instance-repairs", + "services": [ + "VM" ], "severity": "Low", - "subcategory": "Subscriptions", - "text": "The Quota API is a REST API that you can use to view and manage quotas for Azure services. Consider using it if necessary." + "subcategory": "VM Scale Sets", + "text": "Enable automatic instance repairs for enhanced VM Scale Sets resiliency", + "waf": "Reliability" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", - "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Ensure that Azure Backup is utilized appropriately to meet your organization's resiliency requirements for Azure virtual machines (VMs).", + "guid": "4d874a74-8b66-42d6-b150-512a66498f6d", + "link": "https://learn.microsoft.com/azure/backup/backup-azure-vms-introduction", "services": [ "VM", - "Subscriptions" + "Backup" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "If deploying to an availability zone, ensure that the VM's zone deployment is available once the quota has been approved. Submit a support request with the subscription, VM series, number of CPUs and availability zone required." + "subcategory": "Virtual Machines", + "text": "Consider Azure Backup to meet your resiliency requirements for Azure VMs", + "waf": "Reliability" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Single Instance VMs using Premium SSD or Ultra Disk for all Operating System Disks and Data Disks are guaranteed to have Virtual Machine Connectivity of at least 99.9%", + "guid": "8052d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "link": "https://learn.microsoft.com/azure/virtual-machines/disks-types", "services": [ - "Subscriptions" + "VM" ], "severity": "High", - "subcategory": "Subscriptions", - "text": "Ensure required services and features are available within the chosen deployment regions eg. ANF , Zone etc.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" + "subcategory": "Virtual Machines", + "text": "Use Premium or Ultra disks for production VMs", + "waf": "Reliability" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Azure automatically replicates managed disks within a region to ensure data durability and protect against single-point failures.", + "guid": "b31e38c3-f298-412b-8363-cffe179b599d", + "link": "https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview", "services": [ - "Subscriptions", - "TrafficManager", - "Cost" + "VM" ], - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Leverage Azure resource tag for cost categorization and resource grouping (: BillTo, Department (or Business Unit), Environment (Production, Stage, Development), Tier (Web Tier, Application Tier), Application Owner, ProjectName)", - "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" + "severity": "High", + "subcategory": "Virtual Machines", + "text": "Ensure Managed Disks are used for all VMs", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "2f7c95f0-6e15-44e3-aa35-92829e6e2061", - "link": "https://learn.microsoft.com/azure/backup/sap-hana-database-about", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Temporary disks are intended for short-term storage of non-persistent data such as page files, swap files, or SQL Server tempdb. Storing persistent data on temporary disks can lead to data loss during maintenance events or VM redeployment.", + "guid": "e0d5973c-d4ce-432c-8881-37f6f7c4c0d4", + "link": "https://learn.microsoft.com/azure/virtual-machines/managed-disks-overview#temporary-disk", "services": [ - "Backup", - "Monitor" + "SQL", + "VM", + "Storage" ], - "severity": "High", - "subcategory": "BCDR", - "text": "Help protect your HANA database by using the Azure Backup service.", - "training": "https://learn.microsoft.com/training/modules/implement-azure-backup-sap-workloads-azure-virtual-machines/?source=recommendations" + "severity": "Medium", + "subcategory": "Virtual Machines", + "text": "Do not use the Temp disk for anything that is not acceptable to be lost", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "302a2fbf-3745-4a5f-a365-c9d1a16ca22c", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/azacsnap-introduction", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Co-locate your compute, storage, networking, and data resources across an availability zone, and replicate this arrangement in other availability zones.", + "guid": "e514548d-2447-4ec6-9138-b8200f1ce16e", + "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "services": [ "VM", - "Entra", "Storage", - "Monitor" + "ACR" ], "severity": "Medium", - "subcategory": "BCDR", - "text": "If you deploy Azure NetApp Files for your HANA, Oracle, or DB2 database, use the Azure Application Consistent Snapshot tool (AzAcSnap) to take application-consistent snapshots. AzAcSnap also supports Oracle databases. Consider using AzAcSnap on a central VM rather than on individual VMs." + "subcategory": "Virtual Machines", + "text": "Leverage Availability Zones for your VMs in regions where they are supported", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "42d37218-a3a7-45df-bff6-1173e7f249ea", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Use at least two VMs in Availability Sets to isolate VMs on different fault and update domains.", + "guid": "5a785d6f-e96c-496a-b884-4cf3b2b38c88", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability-set-overview", "services": [ - "SAP", - "Monitor" + "VM" ], - "severity": "High", - "subcategory": "Management", - "text": "Ensure time-zone matches between the operating system and the SAP system." + "severity": "Medium", + "subcategory": "Virtual Machines", + "text": "For regions that do not support Availability Zones deploy VMs into Availability Sets", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "c3c7abc0-716c-4486-893c-40e181d65539", - "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel-multi-sid", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Azure provides multiple options for VM redundancy to meet different requirements (Availability Zones, Virtual Machine Scale Sets, Availability Sets, Azure Site Recovery)", + "guid": "6ba2c021-4991-414a-9d3c-e574dccbd979", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "services": [ - "Entra", - "Monitor" + "VM", + "ASR" ], - "severity": "Medium", - "subcategory": "Management", - "text": "Don't group different application services in the same cluster. For example, don't combine DRBD and central services clusters on the same cluster. However, you can use the same Pacemaker cluster to manage approximately five different central services (multi-SID cluster).", - "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" + "severity": "High", + "subcategory": "Virtual Machines", + "text": "Avoid running a production workload on a single VM", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "a491dfc4-9353-4213-9217-eef0949f9467", - "link": "https://azure.microsoft.com/pricing/offers/dev-test/", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Azure Site Recovery enables you to achieve low RTO (Recovery Time Objective) for your Azure and hybrid VMs by providing continuous replication and failover capabilities.", + "guid": "2a6bcca2-b5fe-4a1e-af3d-d95d48c7c891", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "services": [ - "Monitor", - "Cost" + "VM", + "AVS", + "ASR" ], - "severity": "Low", - "subcategory": "Management", - "text": "Consider running dev/test systems in a snooze model to save and optimize Azure run costs." + "severity": "High", + "subcategory": "Virtual Machines", + "text": "For Azure and on-premises VMs (Hyper-V/Phyiscal/VMware) with low RTO requirements use Azure Site Recovery", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "b7056168-6199-4732-a514-cdbb2d5c9c54", - "link": "https://learn.microsoft.com/azure/lighthouse/overview", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "By using Capacity Reservations, you can effectively manage capacity for critical workloads, ensuring resource availability in specified regions.", + "guid": "bd7bb012-f7b9-45e0-9e15-8e3ea3992c2d", + "link": "https://learn.microsoft.com/azure/virtual-machines/capacity-reservation-overview", "services": [ - "Entra", - "SAP", - "Monitor" + "VM" ], - "severity": "Medium", - "subcategory": "Management", - "text": "If you partner with customers by managing their SAP estates, consider Azure Lighthouse. Azure Lighthouse allows managed service providers to use Azure native identity services to authenticate to the customers' environment. It puts the control in the hands of customers, because they can revoke access at any time and audit service providers' actions." + "severity": "Low", + "subcategory": "Virtual Machines", + "text": "Use Capacity Reservations for critical workloads that require guaranteed capacity", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "4d116785-d2fa-456c-96ad-48408fe72734", - "link": "https://learn.microsoft.com/azure/update-manager/scheduled-patching?tabs=schedule-updates-single-machine%2Cschedule-updates-scale-overview", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "By ensuring that the necessary quotas are increased in your DR region before testing failover with ASR, you can avoid any potential resource constraints during the recovery process for failed over VMs.", + "guid": "e6e2065b-3a76-4af4-a691-e8939ada4666", + "link": "https://learn.microsoft.com/azure/quotas/per-vm-quota-requests", "services": [ "VM", - "Monitor" + "ASR" ], "severity": "Medium", - "subcategory": "Management", - "text": "Use Azure Update Manager to check the status of available updates for a single VM or multiple VMs and consider scheduling regular patching.", - "training": "https://learn.microsoft.com/training/modules/keep-your-virtual-machines-updated/?source=recommendations" + "subcategory": "Virtual Machines", + "text": "Increase quotas in DR region before testing failover with ASR", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "76c8bcbf-45bb-4e60-ad8a-03e97778424d", - "link": "https://learn.microsoft.com/azure/sap/workloads/lama-installation", + "category": "Compute", + "checklist": "Resiliency Review", + "description": "Scheduled Events is an Azure Metadata Service that provides information about upcoming maintenance events for virtual machines (VMs). By leveraging Scheduled Events, you can proactively prepare your applications for VM maintenance, minimizing disruption and improving the availability of your VMs.", + "guid": "6d3b475a-5c7a-4cbe-99bb-e64dd8902e87", + "link": "https://learn.microsoft.com/azure/virtual-machines/windows/scheduled-events", "services": [ - "SAP", - "Monitor" + "VM" ], "severity": "Low", - "subcategory": "Management", - "text": "Optimize and manage SAP Basis operations by using SAP Landscape Management (LaMa). Use the SAP LaMa connector for Azure to relocate, copy, clone, and refresh SAP systems.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-remote-management/?source=recommendations" + "subcategory": "Virtual Machines", + "text": "Utilize Scheduled Events to prepare for VM maintenance", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "14591147-5e39-4e53-89cc-cd979366bcda", - "link": "https://learn.microsoft.com/azure/sap/monitor/about-azure-monitor-sap-solutions", + "category": "Data", + "checklist": "Resiliency Review", + "description": "Use Zone-redundant Storage (ZRS) in the primary region for scenarios that require high availability and for restricting replication to a particular country or region. For protection against regional disasters, use Geo-zone-redundant Storage (GZRS), which combines ZRS in the primary region with geo-replication to a secondary region?.", + "guid": "48c7c891-dcb1-4f7d-9769-ae568ba38d4a", + "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "services": [ - "SQL", - "SAP", - "Monitor" + "Storage" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Monitor for SAP solutions to monitor your SAP workloads(SAP HANA, high-availability SUSE clusters, and SQL systems) on Azure. Consider supplementing Azure Monitor for SAP solutions with SAP Solution Manager.", - "training": "https://learn.microsoft.com/training/modules/implement-azure-monitoring-sap-workloads-azure-virtual-machines/?source=recommendations" + "subcategory": "Storage Accounts", + "text": "Choose the most appropriate data redundancy option for Azure Storage based on your requirements", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "2750ab1a-b039-4d95-b54c-7c8929cb107d", - "link": "https://learn.microsoft.com/azure/sap/workloads/vm-extension-for-sap", + "category": "Data", + "checklist": "Resiliency Review", + "description": "Assigning a Delete lock to your storage account helps protect the availability of your data, minimizing the risk of disruptions to your business operations.", + "guid": "85e2213d-bd7b-4b01-8f7b-95e06e158e3e", + "link": "https://learn.microsoft.com/azure/storage/common/lock-account-resource", "services": [ - "VM", - "Entra", - "SAP", - "Monitor" + "Storage" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Run a VM Extension for SAP check. VM Extension for SAP uses the assigned managed identity of a virtual machine (VM) to access VM monitoring and configuration data. The check ensures that all performance metrics in your SAP application come from the underlying Azure Extension for SAP.", - "training": "https://learn.microsoft.com/training/modules/configure-azure-enhanced-monitoring-extension-for-sap/?source=recommendations" + "severity": "Low", + "subcategory": "Storage Accounts", + "text": "Apply a Delete lock to prevent accidental or malicious deletion of storage accounts", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "5325ae52-5ba3-44d4-985e-2213ace7bb12", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "category": "Data", + "checklist": "Resiliency Review", + "description": "Container soft delete protects your data from being accidentally deleted by maintaining the deleted data in the system for a specified period of time.", + "guid": "a3992c2d-e6e2-4065-a3a7-6af4a691e893", + "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-enable", "services": [ - "AzurePolicy", - "Monitor" + "Storage" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Azure Policy for access control and compliance reporting. Azure Policy provides the ability to enforce organization-wide settings to ensure consistent policy adherence and fast violation detection. ", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" + "severity": "Low", + "subcategory": "Storage Accounts", + "text": "Enable soft delete for Storage Account Containers", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "523181aa-4174-4269-93ff-8ae7d7d47431", - "link": "https://learn.microsoft.com/azure/network-watcher/connection-monitor-overview", + "category": "Data", + "checklist": "Resiliency Review", + "description": "Blob soft delete protects an individual blob and its versions, snapshots, and metadata from accidental deletes or overwrites by maintaining the deleted data in the system for a specified period of time.", + "guid": "9ada4666-7e13-4c10-96b9-153d89f89dc7", + "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-enable", "services": [ - "SAP", - "NetworkWatcher", - "Monitor" + "Storage" + ], + "severity": "Low", + "subcategory": "Storage Accounts", + "text": "Enable soft delete for blobs", + "waf": "Reliability" + }, + { + "category": "General", + "checklist": "Resiliency Review", + "description": "Azure Backup enhanced soft delete provides critical protection against ransomware attacks by retaining deleted backups, enabling recovery from potential ransomware encryption or deletion.", + "guid": "b44be3b1-a27f-48b9-b91b-e1038df03a82", + "link": "https://learn.microsoft.com/azure/backup/backup-azure-enhanced-soft-delete-about", + "services": [ + "Backup" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Connection Monitor in Azure Network Watcher to monitor latency metrics for SAP databases and application servers. Or collect and display network latency measurements by using Azure Monitor.", - "training": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/collecting-and-displaying-niping-network-latency-measurements/ba-p/1833979" + "subcategory": "Backup", + "text": "Enable Azure Backup enhanced soft delete for improved data protection and recovery", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "d89fd98d-23e4-4b40-a92e-32db9365522c", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-monitor-and-troubleshoot", + "category": "General", + "checklist": "Resiliency Review", + "description": "Azure Backup's multi-user authorization enables fine-grained control over user access to backup resources, allowing you to restrict privileges and ensure proper authentication and authorization for backup operations.", + "guid": "2cd463cb-bbc8-4ac2-a9eb-c92a43da1dae", + "link": "https://learn.microsoft.com/azure/backup/multi-user-authorization-concept", "services": [ - "ASR", - "SAP", - "Monitor" + "Backup" ], - "severity": "High", - "subcategory": "Monitoring", - "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", - "training": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations" + "severity": "Low", + "subcategory": "Backup", + "text": "Implement multi-user authorization for Azure Backup to ensure secure and controlled access to backup resources", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "73686af4-6791-4f89-95ad-a43324e13811", - "link": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/QualityCheck", + "category": "General", + "checklist": "Resiliency Review", + "description": "Azure Immutable Storage provides an additional layer of security by ensuring that backup data stored in the vault cannot be modified or deleted for a specified retention period. This helps safeguard your backups from ransomware attacks that may attempt to compromise or manipulate your backup data.", + "guid": "2cc88147-0607-4c1c-aa0e-614658dd458e", + "link": "https://learn.microsoft.com/azure/backup/backup-azure-immutable-vault-concept?source=recommendations&tabs=recovery-services-vault", "services": [ - "VM", - "SAP", - "Monitor" + "Storage", + "Backup" ], - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Perform a quality check for SAP HANA on the provisioned Azure infrastructure to verify that provisioned VMs comply with SAP HANA on Azure best practices." + "severity": "Low", + "subcategory": "Backup", + "text": "Implement Immutable Storage for your vaults to protect against ransomware and prevent unauthorized modifications to backups", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "616785d6-fa96-4c96-ad88-518f482734c8", - "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-zones", + "category": "General", + "checklist": "Resiliency Review", + "description": "Clearly define your organization's business continuity and disaster recovery requirements for your Azure environment. This includes identifying the critical applications, data, and services that need to be protected, as well as specifying the desired recovery objectives and strategies.", + "guid": "72e52e36-11dd-458c-9a4b-1521e43a58a9", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-business-continuity-disaster-recovery", "services": [ - "Subscriptions", - "SAP", - "Monitor" + "ASR" ], "severity": "High", - "subcategory": "Monitoring", - "text": "For each Azure subscription, run a latency test on Azure availability zones before zonal deployment to choose low-latency zones for deployment of SAP on Azure.", - "training": "https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities/tree/main/AvZone-Latency-Test" + "subcategory": "Design", + "text": "Define business continuity and disaster recovery requirements", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "410adcba-db46-424f-a6c4-05ecde75c52e", - "link": "https://learn.microsoft.com/azure/advisor/advisor-how-to-improve-reliability", + "category": "General", + "checklist": "Resiliency Review", + "description": "Ensure that your Azure architectures are designed with a focus on reliability. Consider implementing fault-tolerant mechanisms, redundancy, and resiliency patterns to minimize the impact of failures and maximize the availability of your applications and services.", + "guid": "c2399c4d-7b67-4d0c-9555-62f2b3e4563a", + "link": "https://learn.microsoft.com/azure/architecture/reliability/architect", + "services": [], + "severity": "High", + "subcategory": "Design", + "text": "Implement reliability best practices in Azure architectures", + "waf": "Reliability" + }, + { + "category": "General", + "checklist": "Resiliency Review", + "description": "IaC configurations can play a role in your disaster recovery plan, particularly in situations where recovery time is not time-sensitive. In the event of infrastructure recreation in a second region, IaC can be used to reproduce the necessary infrastructure.", + "guid": "fe237de2-43b1-46c3-8d7a-a9b7570449aa", + "link": "https://learn.microsoft.com/azure/well-architected/devops/automation-infrastructure", "services": [ - "ASR", - "Storage", - "Monitor" + "RBAC", + "ASR" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Run the Resiliency Report to ensure that the configuration of the entire provisioned Azure infrastructure (Compute, Database, Networking, Storage, Site Recovery) complies with the configuration defined by Cloud Adaption Framework for Azure.", - "training": "https://learn.microsoft.com/training/paths/azure-well-architected-framework/" + "subcategory": "DevOps", + "text": "Implement Infrastructure as Code (IaC) for Rapid Infrastructure Recovery", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "86ba2802-1459-4114-95e3-9e5309cccd97", - "link": "https://learn.microsoft.com/azure/sentinel/sap/deployment-overview", + "category": "General", + "checklist": "Resiliency Review", + "description": "Azure offers region pairs that are geographically separated and can be used for cross-region replication and disaster recovery. These region pairs provide redundancy and protection against regional or large-scale disasters.", + "guid": "dcb1f7d5-769a-4e56-aba3-8d4a85e2213d", + "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "services": [ - "Sentinel", - "SAP", - "Monitor" + "ASR" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Implement threat protection by using the Microsoft Sentinel solution for SAP. Use this solution to monitor your SAP systems and detect sophisticated threats throughout the business logic and application layers.", - "training": "https://learn.microsoft.com/training/modules/plan-microsoft-sentinel-deployment-sap/?source=recommendations" + "subcategory": "Multi-region", + "text": "Plan for cross-region recovery by leveraging region pairs", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "579266bc-ca27-45fa-a1ab-fe9d55d04c3c", - "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/enable-tag-inheritance", + "category": "Network", + "checklist": "Resiliency Review", + "description": "By deploying an Application Gateway with a minimum instance count of two, you will have at least two instances available under normal circumstances. In the event that one of the instances encounters a problem, the other instance will handle the traffic while a new instance is being created. This approach significantly reduces the risk of service disruption and ensures a seamless experience for your users.", + "guid": "93c76286-37a5-451c-9b04-e4f1854387e5", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant#autoscaling-and-high-availability", "services": [ - "Monitor", - "Cost" + "AppGW" ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Azure tagging can be leveraged to logically group and track resources, automate their deployments, and most importantly, provide visibility on the incurred costs.", - "training": "https://learn.microsoft.com/training/modules/analyze-costs-create-budgets-azure-cost-management/?source=recommendations" + "subcategory": "Application Gateways", + "text": "Deploy Application Gateways with a minimum instance count of 2 to avoid instance provisioning downtime", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "04b8e5e5-13cb-4b22-af62-5a8ecfcf0337", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-test-latency?tabs=windows", + "category": "Network", + "checklist": "Resiliency Review", + "description": "The v2 SKU offers several advantages and critical new features that enhance the availability and resilience of your application infrastructure. One notable feature supported by the v2 SKU is zone redundancy, which allows an Application Gateway deployment to span multiple Availability Zones.", + "guid": "ced126cd-032a-4f5b-8fc6-998a535e3378", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "services": [ - "VM", - "Monitor" + "Storage", + "AppGW" ], - "severity": "Low", - "subcategory": "Performance", - "text": "Use inter-VM latency monitoring for latency-sensitive applications." + "severity": "High", + "subcategory": "Application Gateways", + "text": "Deploy Azure Application Gateway v2 for zone redundancy support", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "07e5ed53-3d96-43d8-87ea-631b77da5aba", - "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide-storage", + "category": "Network", + "checklist": "Resiliency Review", + "description": "Azure Front Door provides automatic failover capabilities, ensuring continuity in the event of a primary region becoming unavailable. However, during the failover process, there may be a brief period (typically 20-60 seconds) when clients cannot reach the application. It is essential to review the Azure Front Door service level agreement (SLA) to determine whether relying solely on Front Door meets your business requirements for high availability. ", + "guid": "97e31c67-d68c-4f6a-92a1-194956d697dc", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/app-service-web-app/multi-region#azure-front-door", "services": [ - "ASR", - "SAP", - "Monitor" + "FrontDoor" ], - "severity": "Medium", - "subcategory": "Performance", - "text": "Use Azure Site Recovery monitoring to maintain the health of the disaster recovery service for SAP application servers.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-storage/?source=recommendations" + "severity": "Low", + "subcategory": "Azure Front Door", + "text": "Consider a redundant traffic management solution in conjunction with Azure Front Door", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "abb6af9c-982c-4cf1-83fb-329fafd1ee56", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-management-and-monitoring", + "category": "Network", + "checklist": "Resiliency Review", + "description": "By implementing Traffic Manager, you can configure it to continuously monitor the health of your application endpoints and automatically redirect traffic to an alternate endpoint when necessary. This automation minimizes downtime and provides a more seamless experience for your users during disaster recovery scenarios.", + "guid": "8df03a82-2cd4-463c-abbc-8ac299ebc92a", + "link": "https://learn.microsoft.com/azure/networking/disaster-recovery-dns-traffic-manager", "services": [ - "Storage", - "SAP", - "Monitor" + "TrafficManager", + "DNS", + "Monitor", + "ASR" ], - "severity": "Medium", - "subcategory": "Performance", - "text": "Exclude all the database file systems and executable programs from antivirus scans. Including them could lead to performance problems. Check with the database vendors for prescriptive details on the exclusion list. For example, Oracle recommends excluding /oracle//sapdata from antivirus scans." + "severity": "Low", + "subcategory": "DNS", + "text": "Plan for automated failover using Traffic Manager for DNS Traffic", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "c027f893-f404-41a9-b33d-39d625a14964", - "link": "https://sapit-forme-prod.authentication.eu11.hana.ondemand.com/login", + "category": "Network", + "checklist": "Resiliency Review", + "description": "To eliminate a single point of failure in your on-premises DNS services and ensure reliable DNS resolution during business continuity and disaster recovery scenarios, it is recommended to utilize Azure DNS Private Resolvers in multiple regions. By deploying two or more Azure DNS private resolvers across different regions, you can enable DNS failover and achieve resiliency in your DNS infrastructure.", + "guid": "43da1dae-2cc8-4814-9060-7c1cca0e6146", + "link": "https://learn.microsoft.com/azure/dns/tutorial-dns-private-resolver-failover", "services": [ - "SAP", - "Monitor" + "DNS", + "ACR", + "ASR" ], "severity": "Low", - "subcategory": "Performance", - "text": "Consider collecting full database statistics for non-HANA databases after migration. For example, implement SAP note 1020260 - Delivery of Oracle statistics." + "subcategory": "DNS", + "text": "Implement DNS Failover using Azure DNS Private Resolvers", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "fdafb1f5-3eee-4354-a8c9-deb8127ebc2e", - "link": "https://learn.microsoft.com/azure/virtual-machines/workloads/oracle/configure-oracle-asm", + "category": "Network", + "checklist": "Resiliency Review", + "description": "Use an on-premises data gateway cluster to avoid single points of failure and to load balance traffic across gateways.", + "guid": "89f89dc7-b44b-4e3b-8a27-f8b9e91be103", + "link": "https://learn.microsoft.com/data-integration/gateway/service-gateway-high-availability-clusters", "services": [ - "Storage", - "SAP", - "Monitor" + "ACR" ], "severity": "Medium", - "subcategory": "Performance", - "text": "Consider using Oracle Automatic Storage Management (ASM) for all Oracle deployments that use SAP on Azure.", - "training": "https://learn.microsoft.com/training/paths/administer-infrastructure-resources-in-azure/?source=recommendations" + "subcategory": "Data Gateways", + "text": "Use on-premises data gateway clusters to ensure high availability for business-critical data", + "waf": "Reliability" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "33c5d5bf-daf3-4f0d-bd50-6010fdcec22e", - "link": "https://techcommunity.microsoft.com/t5/running-sap-applications-on-the/announcement-sap-on-azure-oracle-performance-efficiency-scripts/ba-p/3725178", + "category": "Network", + "checklist": "Resiliency Review", + "description": "When using ExpressRoute, it's important to design for high availability by incorporating redundancy in both the partner and customer networks. This can include multiple ExpressRoute circuits, redundant connections from your network to Microsoft, and ensuring your on-premises network equipment has redundant connections.", + "guid": "c0e7c28d-c936-4657-802b-ff4564b0d934", + "link": "https://learn.microsoft.com/azure/expressroute/designing-for-high-availability-with-expressroute", "services": [ - "SQL", - "SAP", - "Monitor" + "ExpressRoute" ], "severity": "Medium", - "subcategory": "Performance", - "text": "For SAP on Azure running Oracle, a collection of SQL scripts can help you diagnose performance problems. Automatic Workload Repository (AWR) reports contain valuable information for diagnosing problems in the Oracle system. We recommend that you run an AWR report during several sessions and choose peak times for it, to ensure broad coverage for the analysis.", - "training": "https://learn.microsoft.com/ja-jp/azure/well-architected/oracle-iaas/performance-efficiency" + "subcategory": "ExpressRoute", + "text": "Ensure redundancy within both the partner network and customer network when utilizing ExpressRoute for high availability", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5ba34d46-85e2-4213-ace7-bb122f7c95f0", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", - "services": [ - "AzurePolicy", - "AppGW", - "WAF" + "category": "Network", + "checklist": "Resiliency Review", + "description": "The primary circuit should handle regular traffic while the backup circuit stays ready to take over if the primary circuit fails. Utilize BGP attributes to influence routing and designate your primary and backup circuits effectively.", + "guid": "a359c373-e7dd-4616-83a3-64a907ebae48", + "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering", + "services": [ + "ExpressRoute", + "Backup" ], "severity": "Medium", - "subcategory": "App delivery", - "text": "For secure delivery of HTTP/S apps, use Application Gateway v2 and ensure that WAF protection and policies are enabled.", - "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/" + "subcategory": "ExpressRoute", + "text": "When using multiple ExpressRoute circuits ensure that routing allows for a primary and backup", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "fa9d30bc-1b82-4e4b-bfdf-6b017938b9e6", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", + "category": "Network", + "checklist": "Resiliency Review", + "description": "S2S VPN connection can provide a cost-effective, resilient backup solution in the event of an ExpressRoute circuit failure. By using S2S VPN as a failover, you can maintain connectivity to your Azure resources without relying solely on ExpressRoute.", + "guid": "ead53cc7-de2e-48aa-ab35-71549ab9153d", + "link": "https://learn.microsoft.com/azure/expressroute/use-s2s-vpn-as-backup-for-expressroute-privatepeering", "services": [ - "VM", - "DNS", - "SAP" + "ExpressRoute", + "VPN", + "Cost", + "Backup" ], - "severity": "Medium", - "subcategory": "DNS", - "text": "If the virtual machine's DNS or virtual name is not changed during migration to Azure, Background DNS and virtual names connect many system interfaces in the SAP landscape, and customers are only sometimes aware of the interfaces that developers define over time. Connection challenges arise between various systems when virtual or DNS names change after migrations, and it's recommended to retain DNS aliases to prevent these types of difficulties.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" + "severity": "Low", + "subcategory": "ExpressRoute", + "text": "Consider deploying site-to-site VPN as a backup for your ExpressRoute private peering", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a2858f78-105b-4f52-b7a9-5b0f4439743b", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity", + "category": "Network", + "checklist": "Resiliency Review", + "description": "Standard Load Balancer SKU offers an SLA of 99.99% and a higher level of service availability compared to the Basic Load Balancer SKU.", + "guid": "778468d5-5a78-45d6-be96-c96ad8844cf3", + "link": "https://learn.microsoft.com/azure/load-balancer/skus", "services": [ - "VNet", - "DNS", - "SAP" + "LoadBalancer" ], "severity": "Medium", - "subcategory": "DNS", - "text": "Use different DNS zones to distinguish each environment (sandbox, development, preproduction, and production) from each other. The exception is for SAP deployments with their own VNet; here, private DNS zones might not be necessary.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/4-explore-name-resolution" + "subcategory": "Load Balancers", + "text": "Leverage the Standard SKU for Load Balancers that handle traffic to production applications", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a3592829-e6e2-4061-9368-6af46791f893", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", + "category": "Network", + "checklist": "Resiliency Review", + "description": "By configuring the load balancer with a zone-redundant frontend, it can serve zonal resources in any zone with a single IP address. As long as at least one zone remains healthy within the region, the IP address associated with the frontend can survive one or more zone failures. It is recommended to have multiple zonal resources, such as virtual machines from different zones, in the backend pool of the load balancer. ", + "guid": "b2b38c88-6ba2-4c02-8499-114a5d3ce574", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-standard-availability-zones", "services": [ - "VNet", - "ACR", - "SAP" + "VM", + "LoadBalancer" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Local and global VNet peering provide connectivity and are the preferred approaches to ensure connectivity between landing zones for SAP deployments across multiple Azure regions", - "training": "https://learn.microsoft.com/training/modules/configure-vnet-peering/?source=recommendations" + "severity": "Low", + "subcategory": "Load Balancers", + "text": "For load balancers, consider using a zone-redundant frontend with multiple zonal resources in the backend", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "41742694-3ff8-4ae7-b7d4-743176c8bcbf", - "link": "https://learn.microsoft.com/azure/sap/workloads/planning-guide", + "category": "Network", + "checklist": "Resiliency Review", + "description": "When designing health probes for your Azure Load Balancer, it is important to follow best practices to ensure reliable and accurate monitoring of your backend instances.", + "guid": "dccbd979-2a6b-4cca-8b5f-ea1ebf3dd95d", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-custom-probe-overview#design-guidance", "services": [ - "NVA", - "SAP" + "Monitor", + "LoadBalancer" ], - "severity": "High", - "subcategory": "Hybrid", - "text": "It is not supported to deploy any NVA between SAP application and SAP Database server", - "training": "https://me.sap.com/notes/2731110" + "severity": "Low", + "subcategory": "Load Balancers", + "text": "Select the right protocol, appropriate intervals and timeouts, representative paths and probe responses when defining Load Balancer Health Probes", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "7d4bc7d2-c34a-452e-8f1d-6ae3c8eafcc3", - "link": "https://learn.microsoft.com/training/modules/introduction-azure-virtual-wan/?source=recommendations", + "category": "Network", + "checklist": "Resiliency Review", + "description": "When choosing the best option for deploying NVAs in Azure, it is crucial to consider the vendor's recommendations and validate that the specific design has been vetted and validated by the NVA vendor. The vendor should also provide the necessary NVA configuration for seamless integration in Azure.", + "guid": "8b1188b3-c6a4-46ce-a544-451e192d3442", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", "services": [ - "SAP", - "ACR", - "VWAN" + "NVA" ], - "severity": "Medium", - "subcategory": "Hybrid", - "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", - "training": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" + "severity": "High", + "subcategory": "NVAs", + "text": "Deploy Network Virtual Appliances (NVAs) in a vendor supported configuration for High Availability", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "0cedb1f6-ae6c-492b-8b17-8061f50b16d3", - "link": "https://learn.microsoft.com/azure/well-architected/services/networking/network-virtual-appliances/reliability", + "category": "Network", + "checklist": "Resiliency Review", + "description": "By deploying VPN Gateways in an active-active mode, you can distribute VPN traffic across multiple gateways, improving reliability and ensuring continuous connectivity in case of failures or maintenance.", + "guid": "927139b8-2110-42db-b6ea-f11e6f843e53", + "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-highlyavailable", "services": [ - "VNet", - "NVA" + "VPN", + "ACR" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "Consider deploying network virtual appliances (NVAs) between regions only if partner NVAs are used. NVAs between regions or VNets aren't required if native NVAs are present. When you're deploying partner networking technologies and NVAs, follow the vendor's guidance to verify conflicting configurations with Azure networking.", - "training": "https://learn.microsoft.com/training/modules/control-network-traffic-flow-with-routes/?source=recommendations" + "subcategory": "VPN Gateways", + "text": "Deploy Azure VPN Gateways in an active-active mode to ensure high availability and redundancy for your VPN connections.", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "facc08c6-ea95-4641-91cd-fa09e573adbd", - "link": "https://learn.microsoft.com/azure/architecture/networking/hub-spoke-vwan-architecture", + "category": "Network", + "checklist": "Resiliency Review", + "description": "Zone-redundant SKUs ensure that your VPN gateways are physically and logically separated within a region, providing resiliency and scalability. This deployment configuration safeguards your on-premises network connectivity to Azure from zone-level failures.", + "guid": "f4722d92-8c1b-41cd-921f-54b29b9de39a", + "link": "https://learn.microsoft.com/azure/vpn-gateway/about-zone-redundant-vnet-gateways", "services": [ - "VNet", - "NVA", - "SAP", - "VWAN" + "VPN" ], "severity": "Medium", - "subcategory": "Hybrid", - "text": "Virtual WAN manages connectivity between spoke VNets for virtual-WAN-based topologies (no need to set up user-defined routing [UDR] or NVAs), and maximum network throughput for VNet-to-VNet traffic in the same virtual hub is 50 gigabits per second. If necessary, SAP landing zones can use VNet peering to connect to other landing zones and overcome this bandwidth limitation.", - "training": "https://learn.microsoft.com/training/modules/hub-and-spoke-network-architecture/?source=recommendations" + "subcategory": "VPN Gateways", + "text": "Use zone-redundant SKUs when deploying VPN Gateways to enhance resilience and protect against zone-level failures", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "82734c88-6ba2-4802-8459-11475e39e530", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable image export to prevent data exfiltration. Note that this will prevent image import of images into another ACR instance.", + "guid": "ab91932c-9fc9-4d1b-a880-37f5e6bfcb9e", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/container-registry/data-loss-prevention", "services": [ - "VM", - "VNet", - "SAP" + "ACR" ], "severity": "High", - "subcategory": "IP plan", - "text": "Public I.P assignment to VM running SAP Workload is not recommended.", - "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" + "subcategory": "Data Protection", + "text": "Disable Azure Container Registry image export", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "9cccd979-366b-4cda-8750-ab1ab039d95d", - "link": "https://learn.microsoft.com/training/modules/protect-on-premises-infrastructure-with-azure-site-recovery/?source=recommendations", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Enable audit compliance visibility by enabling Azure Policy for Azure Container Registry", + "guid": "d503547c-d447-4e82-9128-a7100f1cac6d", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-azure-policy", "services": [ - "VNet", - "ASR" + "ACR", + "AzurePolicy" ], "severity": "High", - "subcategory": "IP plan", - "text": "Consider reserving I.P address on DR side when configuring ASR", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "subcategory": "Data Protection", + "text": "Enable Azure Policies for Azure Container Registry", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "54c7c892-9cb1-407d-9325-ae525ba34d46", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "The Azure Key Vault (AKV) is used to store a signing key that can be utilized by?notation?with the notation AKV plugin (azure-kv) to sign and verify container images and other artifacts. The Azure Container Registry (ACR) allows you to attach these signatures using the?az?or?oras?CLI commands.", + "guid": "d345293c-7639-4637-a551-c5c04e401955", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-tutorial-sign-build-push", "services": [ - "VNet" + "AKV", + "ACR" ], "severity": "High", - "subcategory": "IP plan", - "text": "Avoid using overlapping IP address ranges for production and DR sites.", - "training": "https://learn.microsoft.com/training/modules/design-ip-addressing-for-azure/?source=recommendations" + "subcategory": "Data Protection", + "text": "Sign and Verify containers with notation (Notary v2)", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6e154e3a-a359-4282-ae6e-206173686af4", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-delegate-subnet", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Azure Container Registry automatically encrypts images and other artifacts that you store. By default, Azure automatically encrypts the registry content at rest by using service-managed keys. By using a customer-managed key, you can supplement default encryption with an additional encryption layer.", + "guid": "0bd05dc2-efd5-4d76-8d41-d2500cc47b49", + "id": "A01.04", + "link": "https://learn.microsoft.com/azure/container-registry/tutorial-customer-managed-keys", "services": [ - "VNet", - "Storage" + "AKV", + "ACR" ], "severity": "Medium", - "subcategory": "IP plan", - "text": "While Azure does help you to create multiple delegated subnets in a VNet, only one delegated subnet can exist in a VNet for Azure NetApp Files. Attempts to create a new volume will fail if you use more than one delegated subnet for Azure NetApp Files.", - "training": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-network-topologies?source=recommendations" + "subcategory": "Data Protection", + "text": "Encrypt registry with a customer managed key", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d8a03e97-7784-424d-9167-85d6fa96c96a", - "link": "https://learn.microsoft.com/azure/well-architected/services/networking/azure-firewall?toc=%2Fazure%2Ffirewall%2Ftoc.json&bc=%2Fazure%2Ffirewall%2Fbreadcrumb%2Ftoc.json", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Use managed identities to secure ACRPull/Push RBAC access from client applications", + "guid": "8f42d78e-79dc-47b3-9bd2-a1a27e7a8e90", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", "services": [ - "Firewall" + "Entra", + "RBAC", + "ACR" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Firewall to govern Azure outbound traffic to the internet, non-HTTP/S inbound connections, and East/West traffic filtering (if the organization requires it)", - "training": "https://learn.microsoft.com/training/paths/secure-networking-infrastructure/" + "severity": "High", + "subcategory": "Identity and Access Control", + "text": "Use Managed Identities to connect instead of Service Principals", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d88518f4-8273-44c8-a6ba-280214591147", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "The local Administrator account is disabled by default and should not be enabled. Use either Token or RBAC-based access methods instead", + "guid": "be0e38ce-e297-411b-b363-caaab79b198d", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", "services": [ - "AppGW", - "SAP" + "Entra", + "RBAC", + "ACR" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use SAP Web dispatcher or third party service like NetScaler in conjunction with Application gateway if necessary to overcome reverse proxy limitation for SAP web Apps." + "severity": "High", + "subcategory": "Identity and Access Control", + "text": "Disable local authentication for management plane access", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5e39e530-9ccc-4d97-a366-bcda2750ab1a", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable Administrator account and assign RBAC roles to principals for ACR Pull/Push operations", + "guid": "387e5ced-126c-4d13-8af5-b20c6998a646", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-roles?tabs=azure-cli", "services": [ - "FrontDoor", - "ACR", - "AzurePolicy", - "WAF" + "Entra", + "RBAC", + "ACR" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Azure Front Door and WAF policies to provide global protection across Azure regions for inbound HTTP/S connections to a landing zone.", - "training": "https://learn.microsoft.com/training/paths/secure-application-delivery/" + "severity": "High", + "subcategory": "Identity and Access Control", + "text": "Assign AcrPull & AcrPush RBAC roles rather than granting Administrative access to identity principals", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b039d95d-54c7-4c89-89cb-107d5325ae52", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable anonymous pull/push access", + "guid": "e338997e-41c7-47d7-acf6-a62a1194956d", + "id": "A02.04", + "link": "https://learn.microsoft.com/azure/container-registry/anonymous-pull-access#configure-anonymous-pull-access", "services": [ - "FrontDoor", - "AzurePolicy", - "AppGW", - "WAF" + "Entra", + "ACR" ], "severity": "Medium", - "subcategory": "Internet", - "text": "Take advantage of Web Application Firewall policies in Azure Front Door when you're using Azure Front Door and Application Gateway to protect HTTP/S applications. Lock down Application Gateway to receive traffic only from Azure Front Door.", - "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" + "subcategory": "Identity and Access Control", + "text": "Disable Anonymous pull access", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5ada4332-4e13-4811-9231-81aa41742694", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Token authentication doesn't support assignment to an AAD principal. Any tokens provided are able to be used by anyone who can access the token", + "guid": "698dc3a2-fd27-4b2e-8870-1a1252beedf6", + "id": "A02.05", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication?tabs=azure-cli", "services": [ - "LoadBalancer", - "AppGW", - "WAF" + "Entra", + "ACR" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use a web application firewall to scan your traffic when it's exposed to the internet. Another option is to use it with your load balancer or with resources that have built-in firewall capabilities like Application Gateway or third-party solutions.", - "training": "https://learn.microsoft.com/training/modules/introduction-azure-web-application-firewall/?source=recommendations" + "severity": "High", + "subcategory": "Identity and Access Control", + "text": "Disable repository-scoped access tokens", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e73de7d5-6f36-4217-a526-e1a621ecddde", - "link": "https://learn.microsoft.com/azure/frontdoor/front-door-overview", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Deploy container images to an ACR behind a Private endpoint within a trusted network", + "guid": "b3bec3d4-f343-47c1-936d-b55f27a71eee", + "id": "A02.06", "services": [ - "SAP", + "EventHubs", + "Entra", "ACR", - "VWAN" + "PrivateLink" ], - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Virtual WAN for Azure deployments in new, large, or global networks where you need global transit connectivity across Azure regions and on-premises locations. With this approach, you won't need to manually set up transitive routing for Azure networking, and you can follow a standard for SAP on Azure deployments.", - "training": "https://learn.microsoft.com/training/modules/explore-azure-networking/10-explore-azure-front-door" + "severity": "High", + "subcategory": "Identity and Access Control", + "text": "Deploy images from a trusted environment", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "3c536a3e-1b6b-4e87-95ca-15edb47251c0", - "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Only tokens with an ACR audience can be used for authentication. Used when enabling Conditional access policies for ACR", + "guid": "3a041fd3-2947-498b-8288-b3c6a56ceb54", + "id": "A02.07", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-enable-conditional-access-policy", "services": [ - "Storage", - "VNet", - "Backup", - "PrivateLink", - "ACR" + "Entra", + "ACR", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Internet", - "text": "To prevent data leakage, use Azure Private Link to securely access platform as a service resources like Azure Blob Storage, Azure Files, Azure Data Lake Storage Gen2, Azure Data Factory, and more. Azure Private Endpoint can also help to secure traffic between VNets and services like Azure Storage, Azure Backup, and more. Traffic between your VNet and the Private Endpoint enabled service travels across the Microsoft global network, which prevents its exposure to the public internet.", - "training": "https://learn.microsoft.com/training/modules/design-implement-private-access-to-azure-services/?source=recommendations" + "subcategory": "Identity and Access Control", + "text": "Disable Azure ARM audience tokens for authentication", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Set up a diagnostic setting to send 'repositoryEvents' & 'LoginEvents' to Log Analytics as the central destination for logging and monitoring. This allows you to monitor control plane activity on the ACR resource itself.", + "guid": "8a488cde-c486-42bc-9bd2-1be77f26e5e6", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/container-registry/monitor-service", "services": [ - "VM", - "SAP" + "Entra", + "Monitor", + "ACR" ], - "severity": "High", - "subcategory": "Segmentation", - "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", - "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" + "severity": "Medium", + "subcategory": "Logging and Monitoring", + "text": "Enable diagnostics logging", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "3ff8ae7d-7d47-4431-96c8-bcbf45bbe609", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-multivip-overview", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Service supports disabling public network access either through using service-level IP ACL filtering rule (not NSG or Azure Firewall) or using a 'Disable Public Network Access' toggle switch", + "guid": "21d41d25-00b7-407a-b9ea-b40fd3290798", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", "services": [ - "LoadBalancer" + "Firewall", + "VNet", + "ACR", + "PrivateLink" ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "Make sure that internal deployments for Azure Load Balancer are set up to use Direct Server Return (DSR). This setting will reduce latency when internal load balancer configurations are used for high-availability configurations on the DBMS layer.", - "training": "https://learn.microsoft.com/ja-jp/training/modules/load-balancing-non-https-traffic-azure/?source=recommendations" + "subcategory": "Network Security", + "text": "Control inbound network access with Private Link", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6791f893-5ada-4433-84e1-3811523181aa", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable public network access if inbound network access is secured using Private Link", + "guid": "cd289ced-6b17-4db8-8554-62f2aee4553a", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-access-selected-networks#disable-public-network-access", "services": [ - "VM", - "VNet", - "SAP" + "ACR", + "PrivateLink" ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "You can use application security group (ASG) and NSG rules to define network security access-control lists between the SAP application and DBMS layers. ASGs group virtual machines to help manage their security.", - "training": "https://learn.microsoft.com/training/modules/configure-network-security-groups/?source=recommendations" + "subcategory": "Network Security", + "text": "Disable Public Network access", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "45bbe609-d8a0-43e9-9778-424d616785d6", - "link": "https://me.sap.com/notes/2015553", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Only the ACR Premium SKU supports Private Link access", + "guid": "fc833934-8b26-42d6-ac5f-512925498f6d", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-skus", "services": [ - "VNet", - "SAP" + "ACR", + "PrivateLink" ], - "severity": "High", - "subcategory": "Segmentation", - "text": "Placing of the SAP application layer and SAP DBMS in different Azure VNets that aren't peered isn't supported.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" + "severity": "Medium", + "subcategory": "Network Security", + "text": "Use an Azure Container Registry SKU that supports Private Link (Premium SKU)", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "fa96c96a-d885-418f-9827-34c886ba2802", - "link": "https://learn.microsoft.com/azure/sap/workloads/proximity-placement-scenarios", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Azure Defender for containers or equivalent service should be used to scan container images for vulnerabilities", + "guid": "bad37dac-43bc-46ce-8d7a-a9b24604489a", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", "services": [ - "SAP" + "Defender", + "ACR" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "For optimal network latency with SAP applications, consider using Azure proximity placement groups.", - "training": "https://learn.microsoft.com/azure/virtual-machines/co-location#planned-maintenance-and-proximity-placement-groups" + "severity": "Low", + "subcategory": "Network Security", + "text": "Enable Defender for Containers to scan Azure Container Registry for vulnerabilities", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "18c8b61c-855a-4405-b6ed-266455e4f4ce", - "link": "https://me.sap.com/notes/2015553", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", + "guid": "4451e1a2-d345-4293-a763-9637a551c5c0", + "id": "A05.01", "services": [ - "SAP" + "ACR" ], - "severity": "High", - "subcategory": "Segmentation", - "text": "It is NOT supported at all to run an SAP Application Server layer and DBMS layer split between on-premise and Azure. Both layers need to completely reside either on-premise or in Azure.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" + "severity": "Medium", + "subcategory": "Vulnerability Management", + "text": "Deploy validated container images", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b65c878b-4b14-4f4e-92d8-d873936493f2", - "link": "https://me.sap.com/notes/2015553", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", + "guid": "4e401955-387e-45ce-b126-cd132af5b20c", + "id": "A05.02", "services": [ - "VNet", - "SAP", - "Cost" + "ACR" ], "severity": "High", - "subcategory": "Segmentation", - "text": "It isn't recommended to host the database management system (DBMS) and application layers of SAP systems in different VNets and connect them with VNet peering because of the substantial costs that excessive network traffic between the layers can produce. Recommend using subnets within the Azure virtual network to separate the SAP application layer and DBMS layer.", - "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-network-topology-and-connectivity" + "subcategory": "Vulnerability Management", + "text": "Use up-to-date platforms, languages, protocols and frameworks", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview?tabs=redhat", + "category": "Application Deployment", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "785c2fa5-5b56-4ad4-a408-fe72734c476b", + "id": "01.01.01", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/containers/aks/secure-baseline-aks", "services": [ - "VM", - "SAP" + "AKS" ], - "severity": "High", - "subcategory": "Segmentation", - "text": "Make sure that Azure accelerated networking is enabled on the VMs used in the SAP application and DBMS layers.", - "training": "https://learn.microsoft.com/training/paths/azure-fundamentals-describe-azure-architecture-services/?source=recommendations" + "severity": "Medium", + "subcategory": "Development", + "text": "Use canary or blue/green deployments", + "waf": "Operations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "402a9846-d515-4061-aff8-cd30088693fa", - "link": "https://learn.microsoft.com/azure/sap/workloads/high-availability-guide-rhel", + "category": "Application Deployment", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "ab5351f6-383a-45ed-9c5e-b143b16db40a", + "id": "01.01.02", + "link": "https://learn.microsoft.com/azure/aks/use-windows-hpc", "services": [ - "LoadBalancer" + "AKS" ], - "severity": "High", - "subcategory": "Segmentation", - "text": "If using Load Balancer with Linux guest operating systems, check that the Linux network parameter net.ipv4.tcp_timestamps is set to 0.", - "training": "https://learn.microsoft.com/training/modules/implement-ha-sap-netweaver-anydb/?source=recommendations" + "severity": "Low", + "subcategory": "Development", + "text": "If required for AKS Windows workloads HostProcess containers can be used", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "87585797-5551-4d53-bb7d-a94ee415734d", - "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration", + "category": "Application Deployment", + "checklist": "Azure AKS Review", + "guid": "a280dcf5-90ce-465d-b8e1-3f9ccbd46926", + "id": "01.01.03", + "link": "https://learn.microsoft.com/azure/azure-functions/functions-kubernetes-keda", + "scale": 1, "services": [ - "VNet", - "SAP" + "AKS" ], - "severity": "Medium", - "subcategory": "Segmentation", - "text": "For SAP RISE/ECS deployments, virtual peering is the preferred way to establish connectivity with customer’s existing Azure environment. Both the SAP vnet and customer vnet(s) are protected with network security groups (NSG), enabling communication on SAP and database ports through the vnet peering" + "severity": "Low", + "simple": -1, + "subcategory": "Development", + "text": "Use KEDA if running event-driven workloads", + "waf": "Performance" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "209d490d-a477-4784-84d1-16785d2fa56c", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Application Deployment", + "checklist": "Azure AKS Review", + "guid": "26886d20-b66c-457b-a591-19bf8e8f5c58", + "id": "01.01.04", + "link": "https://dapr.io/", "services": [ - "Subscriptions", - "RBAC", - "SAP" + "AKS" ], - "severity": "High", - "subcategory": "Governance", - "text": "Customize role-based access control (RBAC) roles for SAP on Azure spoke subscriptions to avoid accidental network-related changes" + "severity": "Low", + "simple": 1, + "subcategory": "Development", + "text": "Use Dapr to ease microservice development", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "56ad4840-8fe7-4273-9c48-6ba280dc0591", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Application Deployment", + "checklist": "Azure AKS Review", + "guid": "3acbe04b-be20-49d3-afda-47778424d116", + "ha": 1, + "id": "01.02.01", + "link": "https://learn.microsoft.com/azure/developer/terraform/create-k8s-cluster-with-tf-and-aks", "services": [ - "PrivateLink", - "NVA", - "SAP" + "AKS" ], "severity": "Medium", - "subcategory": "Governance", - "text": "Isolate DMZs and NVAs from the rest of the SAP estate, configure Azure Private Link, and securely manage and control the SAP on Azure resources" + "simple": -1, + "subcategory": "Infrastructure as Code", + "text": "Use automation through ARM/TF to create your Azure resources", + "waf": "Operations" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "cf65de8e-1309-4ccc-b579-266bcca275fa", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "BC and DR", + "checklist": "Azure AKS Review", + "guid": "36cb45e5-7960-4332-9bdf-8cc23318da61", + "ha": 1, + "id": "02.01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", "services": [ - "SQL", - "Backup", - "Storage", - "SAP" + "AKS", + "ASR" ], - "severity": "Medium", - "subcategory": "Governance", - "text": "For SAP database server encryption, use the SAP HANA native encryption technology. If you're using Azure SQL Database, use Transparent Data Encryption (TDE) offered by the DBMS provider to secure your data and log files, and ensure the backups are also encrypted." + "severity": "High", + "subcategory": "Disaster Recovery", + "text": "Schedule and perform DR tests regularly", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "a1abfe9d-55d0-44c3-a491-9cb1b3d1325a", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "BC and DR", + "checklist": "Azure AKS Review", + "guid": "170265f4-bb46-4a39-9af7-f317284797b1", + "ha": 1, + "id": "02.02.01", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", "services": [ - "Storage" + "AKS", + "TrafficManager", + "LoadBalancer", + "FrontDoor" ], "severity": "Medium", - "subcategory": "Governance", - "text": "Azure Storage encryption is enabled by default" + "subcategory": "High Availability", + "text": "Use Azure Traffic Manager or Azure Front Door as a global load balancer for region failover", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "e124ba34-df68-45ed-bce9-bd3bb0cdb3b5", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [], + "category": "BC and DR", + "checklist": "Azure AKS Review", + "graph": "resources | where type=='microsoft.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | distinct id,compliant", + "guid": "578a219a-46be-4b54-9350-24922634292b", + "ha": 1, + "id": "02.02.02", + "link": "https://learn.microsoft.com/azure/aks/availability-zones", + "services": [ + "AKS" + ], "severity": "Medium", - "subcategory": "Governance", - "text": " " + "subcategory": "High Availability", + "text": "Use Availability Zones if they are supported in your Azure region", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "5eb2ec14-eeaa-4359-8829-e2edb2173676", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", - "services": [], - "severity": "Medium", - "subcategory": "Governance", - "text": " " + "category": "BC and DR", + "checklist": "Azure AKS Review", + "cost": -2, + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | distinct id,compliant", + "guid": "71d41e36-10cc-457b-9a4b-1410d4395898", + "ha": 2, + "id": "02.02.03", + "link": "https://learn.microsoft.com/azure/aks/uptime-sla", + "services": [ + "AKS" + ], + "severity": "High", + "subcategory": "High Availability", + "text": "Use the SLA-backed AKS offering", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "ce9bd3bb-0cdb-43b5-9eb2-ec14eeaa3592", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview", + "category": "BC and DR", + "checklist": "Azure AKS Review", + "guid": "c1288b3c-6a57-4cfc-9444-51e1a3d3453a", + "ha": 1, + "id": "02.02.04", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", "services": [ - "AKV" + "AKS", + "Cost" ], - "severity": "High", - "subcategory": "Secrets", - "text": "Use Azure Key Vault to store your secrets and credentials" + "severity": "Low", + "simple": -1, + "subcategory": "High Availability", + "text": "Use Disruption Budgets in your pod and deployment definitions", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "829e2edb-2173-4676-aff6-691b4935ada4", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", + "category": "BC and DR", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "3c763963-7a55-42d5-a15e-401955387e5c", + "ha": 1, + "id": "02.02.05", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-geo-replication", "services": [ - "AKV" + "AKS", + "ACR" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "It is recommended to LOCK the Azure Resources post successful deployment to safeguard against unauthorized changes" + "severity": "High", + "subcategory": "High Availability", + "text": "If using a private registry, configure region replication to store images in multiple regions", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "2223ece8-1b12-4318-8a54-17415833fb4a", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "BC and DR", + "checklist": "Azure AKS Review", + "guid": "bc14aea6-e65d-48d9-a3ad-c218e6436b06", + "ha": 1, + "id": "02.03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", "services": [ - "AzurePolicy", - "AKV" + "AKS" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." + "severity": "High", + "subcategory": "Requirements", + "text": "Define non-functional requirements such as SLAs, RTO (Recovery Time Objective) and RPO (Recovery Point Objective).", + "waf": "Reliability" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "e3c2df74-3165-4c3a-abe0-5bbe209d490d", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "f82cb8eb-8c0a-4a63-a25a-4956eaa8dc4a", + "id": "03.01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/aks/eslz-cost-governance-with-kubecost", "services": [ - "RBAC", - "AzurePolicy", - "AKV" + "AKS", + "Cost" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Based on existing requirements, regulatory and compliance controls (internal/external) - Determine what Azure Policies and Azure RBAC role are needed" + "severity": "Low", + "subcategory": "Cost", + "text": "Use an external application such as kubecost to allocate costs to different users", + "waf": "Cost" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "a4777842-4d11-4678-9d2f-a56c56ad4840", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "4d3dfbab-9924-4831-a68d-fdf0d72f462c", + "id": "03.01.02", + "link": "https://learn.microsoft.com/azure/aks/scale-down-mode", "services": [ - "AKV", - "AzurePolicy", - "SAP", - "Defender" + "AKS", + "Cost" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "When you enable Microsoft Defender for Cloud Standard for SAP, make sure to exclude the SAP database servers from any policy that installs endpoint protection." + "severity": "Low", + "subcategory": "Cost", + "text": "Use scale down mode to delete/delallocate nodes", + "waf": "Cost" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "8fe72734-c486-4ba2-a0dc-0591cf65de8e", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "87e651ea-bc4a-4a87-a6df-c06a4b570ebc", + "id": "03.01.03", + "link": "https://learn.microsoft.com/azure/aks/gpu-multi-instance", "services": [ - "RBAC", - "SAP", - "AKV" + "AKS", + "Cost" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Delegate an SAP admin custom role with just-in-time access." + "subcategory": "Cost", + "text": "When required use multi-instance partioning GPU on AKS Clusters", + "waf": "Cost" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "1309cccd-5792-466b-aca2-75faa1abfe9d", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "2b72a08b-0410-4cd6-9093-e068a5cf27e8", + "id": "03.01.04", + "link": "https://learn.microsoft.com/azure/aks/start-stop-nodepools", "services": [ - "SAP", - "AKV" + "AKS", + "Cost" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "encrypt data in transit by integrating the third-party security product with secure network communications (SNC) for DIAG (SAP GUI), RFC, and SPNEGO for HTTPS" + "severity": "Low", + "subcategory": "Cost", + "text": "If running a Dev/Test cluster use NodePool Start/Stop", + "waf": "Cost" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "55d04c3c-4919-4cb1-a3d1-325ae124ba34", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==true) | distinct id,compliant", + "guid": "9ca48e4a-85e2-4223-bce8-bb12307ca5f1", + "id": "04.01.01", + "link": "https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes", + "security": 1, "services": [ - "Entra", - "SAP", - "AKV" + "AKS", + "AzurePolicy" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Azure Active Directory (Azure AD) with SAML 2.0 can also provide SSO to a range of SAP applications and platforms like SAP NetWeaver, SAP HANA, and the SAP Cloud Platform" + "simple": -1, + "subcategory": "Compliance", + "text": "Use Azure Policy for Kubernetes to ensure cluster compliance", + "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "df685edd-ce9b-4d3b-a0cd-b3b55eb2ec14", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "graph": "where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1)", + "guid": "6f158e3e-a3a9-42c2-be7e-2165c3a87af4", + "id": "04.01.02", + "link": "https://learn.microsoft.com/azure/aks/use-system-pools", + "security": 1, "services": [ - "SAP", - "AKV" + "AKS" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Make sure you harden the operating system to eradicate vulnerabilities that could lead to attacks on the SAP database." + "simple": -1, + "subcategory": "Compliance", + "text": "Separate applications from the control plane with user/system nodepools", + "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "eeaa3592-829e-42ed-a217-3676aff6691b", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "guid": "a7a1f893-9bda-4477-98f2-4c116775c2ea", + "ha": 1, + "id": "04.01.03", + "link": "https://learn.microsoft.com/azure/aks/use-system-pools", "services": [ - "AKV" + "AKS" ], - "severity": "Medium", - "subcategory": "Secrets", - "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." + "severity": "Low", + "simple": -1, + "subcategory": "Compliance", + "text": "Add taint to your system nodepool to make it dedicated", + "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "4935ada4-2223-4ece-a1b1-23181a541741", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "guid": "55b46a94-8008-4ae7-b7e4-b475b6c8bdbf", + "id": "04.01.04", + "link": "https://learn.microsoft.com/azure/container-registry/", + "security": 1, "services": [ - "AKV" + "AKS", + "ACR" ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Use an Azure Key Vault per application per environment per region." + "simple": -1, + "subcategory": "Compliance", + "text": "Use a private registry for your images, such as ACR", + "waf": "Security" }, { - "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", - "guid": "5833fb4a-e3c2-4df7-9316-5c3acbe05bbe", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "59bce65d-e8a0-43f9-9879-468d66a786d6", + "id": "04.01.05", + "link": "https://learn.microsoft.com/azure/security-center/container-security", + "security": 1, "services": [ - "AKV" + "AKS" ], "severity": "Medium", - "subcategory": "Secrets", - "text": " " + "subcategory": "Compliance", + "text": "Scan your images for vulnerabilities", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Landing Zone Review", - "guid": "d579266b-cca2-475f-aa1a-bfe9d55d04c3", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "cc639637-a652-42ac-89e8-06965388e9de", + "id": "04.01.06", + "link": "https://learn.microsoft.com/azure/security-center/container-security", + "security": 1, "services": [ - "SQL", - "Storage" + "AKS", + "Defender" ], "severity": "Medium", - "subcategory": " ", - "text": "Disk config for Oracle, SQL, HANA" + "subcategory": "Compliance", + "text": "Use Azure Security Center to detect security posture vulnerabilities", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "54174158-33fb-43ae-9c2d-e743165c3acb", - "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "42d4aefe-2383-470e-b019-c30df24996b2", + "id": "04.01.07", + "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool", + "security": 1, "services": [ - "Subscriptions", - "Defender" + "AKS" ], - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Security Center/Defender enable in all subscriptions" + "severity": "Low", + "subcategory": "Compliance", + "text": "If required configure FIPS", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "349f0364-d28d-442e-abbb-c868255abc91", - "link": "https://learn.microsoft.com/azure/security-center/enable-azure-defender", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "guid": "d167dd18-2b0a-4c24-8b99-9a646f8389a7", + "id": "04.01.08", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-cluster-isolation", + "security": 1, "services": [ - "Defender", - "Monitor" + "AKS" ], "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Security Center/Defender enabled on all Log Analytics workspaces" + "subcategory": "Compliance", + "text": "Define app separation requirements (namespace/nodepool/cluster)", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "64e9a19a-e28c-484c-93b6-b7818ca0e6c4", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/enable-data-collection?tabs=autoprovision-feature#what-event-types-are-stored-for-common-and-minimal", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "guid": "5e3df584-eccc-4d97-a3b6-bcda3b50eb2e", + "id": "04.02.01", + "link": "https://github.com/Azure/secrets-store-csi-driver-provider-azure", + "security": 1, "services": [ - "Defender" + "AKS", + "AKV" ], "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Data collection set to 'Common'" + "simple": -1, + "subcategory": "Secrets", + "text": "Store your secrets in Azure Key Vault with the CSI Secrets Store driver", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "2149d414-a923-4c35-94d1-1029bd6aaf11", - "link": "https://learn.microsoft.com/azure/security-center/enable-azure-defender", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "guid": "b03dda6d-58d7-4c89-8ddb-107d5769ae66", + "id": "04.02.02", + "link": "https://learn.microsoft.com/azure/aks/update-credentials", + "security": 1, "services": [ - "Defender" + "AKS", + "AKV" ], "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Defender for Cloud enhanced security features are all enabled" + "subcategory": "Secrets", + "text": "If using Service Principals for the cluster, refresh credentials periodically (like quarterly)", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "e6b84ee5-ef43-4d29-a248-1718d5d1f5f7", - "link": "https://learn.microsoft.com/azure/security-center/security-center-enable-data-collection", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "e7ba73a3-0508-4f80-806f-527db30cee96", + "id": "04.02.03", + "link": "https://learn.microsoft.com/azure/aks/use-kms-etcd-encryption", + "security": 1, "services": [ - "AzurePolicy", - "Defender" + "AKS", + "AKV" ], "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Auto-provisioning enabled as per company policy (policy must exist)" + "subcategory": "Secrets", + "text": "If required add Key Management Service etcd encryption", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "25759e35-680e-4782-9ac9-32213d027ff4", - "link": "https://learn.microsoft.com/azure/security-center/security-center-provide-security-contact-details", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "ec8e4e42-0344-41b0-b865-9123e8956d31", + "id": "04.02.04", + "link": "https://learn.microsoft.com/azure/confidential-computing/confidential-nodes-aks-overview", + "security": 1, "services": [ - "AzurePolicy", - "Defender" + "AKS", + "AKV" ], "severity": "Low", - "subcategory": "Pricing & Settings", - "text": "Email notifications enabled as per company policy (policy must exist)" + "subcategory": "Secrets", + "text": "If required consider using Confidential Compute for AKS", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "12f70993-0631-4583-9ee7-9d6c6d363206", - "link": "https://learn.microsoft.com/azure/security-center/security-center-wdatp?WT.mc_id=Portal-Microsoft_Azure_Security_CloudNativeCompute&tabs=windows", + "category": "Governance and Security", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "c9e95ffe-6dd1-4a17-8c5f-110389ca9b21", + "id": "04.02.05", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-enable", + "security": 1, "services": [ - "Defender" + "AKS", + "Defender", + "AKV" ], "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Enable integrations options are selected " + "subcategory": "Secrets", + "text": "Consider using Defender for Containers", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "5b7abae4-4aad-45e8-a79e-2e86667313c5", - "link": "https://learn.microsoft.com/azure/security-center/defender-for-container-registries-cicd", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | distinct id,compliant", + "guid": "ed127dd1-42b0-46b2-8c69-99a646f3389a", + "id": "05.01.01", + "link": "https://learn.microsoft.com/azure/aks/use-managed-identity", "services": [ - "Defender" + "AKS", + "Entra" ], - "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "CI/CD integration is configured" + "severity": "High", + "simple": 1, + "subcategory": "Identity", + "text": "Use managed identities instead of Service Principals", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "05675c5e-985b-4859-a774-f7e371623b87", - "link": "https://learn.microsoft.com/azure/security-center/continuous-export?tabs=azure-portal", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | distinct id,compliant", + "guid": "7e42c78e-78c0-46a6-8a21-94956e698dc4", + "id": "05.01.02", + "link": "https://learn.microsoft.com/azure/aks/managed-aad", "services": [ - "EventHubs", - "Defender" + "AKS", + "Entra" ], - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Continuous export 'Event Hub' is enabled if using 3rd party SIEM" + "severity": "Medium", + "simple": 1, + "subcategory": "Identity", + "text": "Integrate authentication with AAD (using the managed integration)", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "5a917e1f-349f-4036-9d28-d42e8bbbc868", - "link": "https://learn.microsoft.com/azure/security-center/continuous-export?tabs=azure-portal", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "a2fe27b2-e287-401a-8352-beedf79b488d", + "id": "05.01.03", + "link": "https://learn.microsoft.com/azure/aks/control-kubeconfig-access", + "security": 1, "services": [ - "Sentinel", - "Defender", - "Monitor" + "AKS", + "Entra" ], "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Continuous export 'Log Analytics Workspace' is enabled if not using Azure Sentinel" + "simple": -1, + "subcategory": "Identity", + "text": "Limit access to admin kubeconfig (get-credentials --admin)", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "255abc91-64e9-4a19-ae28-c84c43b6b781", - "link": "https://learn.microsoft.com/azure/security-center/quickstart-onboard-aws?WT.mc_id=Portal-Microsoft_Azure_Security", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "eec4962c-c3bd-421b-b77f-26e5e6b3bec3", + "id": "05.01.04", + "link": "https://learn.microsoft.com/azure/aks/manage-azure-rbac", + "security": 1, "services": [ - "Defender" + "AKS", + "RBAC", + "Entra" ], - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Cloud connector enabled for AWS" + "severity": "Medium", + "simple": -1, + "subcategory": "Identity", + "text": "Integrate authorization with AAD RBAC", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "8ca0e6c4-2149-4d41-9a92-3c3574d11029", - "link": "https://learn.microsoft.com/azure/security-center/quickstart-onboard-gcp", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "d4f3537c-1346-4dc5-9027-a71ffe1bd05d", + "ha": 1, + "id": "05.01.05", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-identity", + "security": 1, "services": [ - "Defender" + "AKS", + "RBAC", + "Entra" ], "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Cloud connector enabled for GCP" + "simple": -1, + "subcategory": "Identity", + "text": "Use namespaces for restricting RBAC privilege in Kubernetes", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "cce9bdf6-b483-45a0-85ec-c8232b230652", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy-integrate-with-microsoft-cloud-application-security", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "d2e0d5d7-71d4-41e3-910c-c57b4a4b1410", + "id": "05.01.06", + "link": "https://learn.microsoft.com/azure/aks/workload-identity-migration-sidecar", + "security": 1, "services": [ - "Entra", - "Defender", - "Monitor" + "AKS", + "Entra" ], - "severity": "Low", - "subcategory": "Pricing & Settings", - "text": "If using Azure AD Application proxy, consider integrating with Microsoft Defender for Cloud Apps to monitor application access in real-time and apply advanced security controls." + "severity": "Medium", + "simple": -1, + "subcategory": "Identity", + "text": "For POD Identity Access Management use Azure AD Workload Identity (preview)", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "df9cc234-18db-4611-9126-5f4bb47a393a", - "link": "https://learn.microsoft.com/azure/security-center/secure-score-security-controls", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "f4dcf690-1b30-407d-abab-6f8aa780d3a3", + "id": "05.01.07", + "link": "https://learn.microsoft.com/azure/aks/managed-aad#non-interactive-sign-in-with-kubelogin", + "security": 1, "services": [ - "Defender" + "AKS", + "Entra" ], "severity": "Medium", - "subcategory": "Recommendations", - "text": "All recommendations remediated or disabled if not required." + "simple": -1, + "subcategory": "Identity", + "text": "For AKS non-interactive logins use kubelogin (preview)", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "description": "Microsoft minimum target for all customers is 70%", - "guid": "08032729-4798-4b15-98a2-19a46ceb5443", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/secure-score-security-controls", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==true) | distinct id,compliant", + "guid": "b085b1f2-3119-4771-8c9a-bbf4411810ec", + "id": "05.01.08", + "link": "https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts", + "security": 1, "services": [ - "Defender" + "AKS", + "Entra" ], - "severity": "High", - "subcategory": "Recommendations", - "text": "Security Score>70%" + "severity": "Medium", + "simple": -1, + "subcategory": "Identity", + "text": "Disable AKS local accounts", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "50259226-4429-42bb-9285-37a55119bf8e", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/tutorial-security-incident", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "36abb0db-c118-4f4c-9880-3f30f9a2deb6", + "id": "05.01.09", + "link": "https://learn.microsoft.com/azure/aks/managed-aad#configure-just-in-time-cluster-access-with-azure-ad-and-aks", + "security": 1, "services": [ - "Defender", - "Monitor" + "AKS", + "Entra" ], - "severity": "Medium", - "subcategory": "Security Alerts", - "text": "Security Alerts contain only those generated in the past 24 hours (remediate or disable older security alerts)" + "severity": "Low", + "simple": -1, + "subcategory": "Identity", + "text": "Configure if required Just-in-time cluster access", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "8f585428-7d9c-4dc1-96cd-072af9b141a8", - "link": "https://learn.microsoft.com/azure/security-center/custom-dashboards-azure-workbooks", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "c4d7f4c6-79bf-45d0-aa05-ce8fc717e150", + "id": "05.01.10", + "link": "https://learn.microsoft.com/azure/aks/managed-aad#use-conditional-access-with-azure-ad-and-aks", + "security": 1, "services": [ - "Defender" + "AKS", + "Entra" ], - "severity": "Medium", - "subcategory": "Workbooks", - "text": "If continuous export is enabled, default workbooks published to custom security dashboard" + "severity": "Low", + "simple": -1, + "subcategory": "Identity", + "text": "Configure if required AAD conditional access for AKS", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "98a535e7-3789-47e7-8ca7-da7be9962a15", - "link": "https://techcommunity.microsoft.com/t5/microsoft-defender-for-cloud/bd-p/MicrosoftDefenderCloud", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "e1123a7c-a333-4eb4-a120-4ee3f293c9f3", + "id": "05.01.11", + "link": "https://learn.microsoft.com/azure/aks/use-group-managed-service-accounts", + "security": 1, "services": [ - "Defender" + "AKS", + "Entra" ], - "severity": "Medium", - "subcategory": "Community", - "text": "Customer is aware of the value of the 'Community' page and has a regular cadence set up to review" + "severity": "Low", + "simple": -1, + "subcategory": "Identity", + "text": "If required for Windows AKS workloads configure gMSA ", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "description": "Customer Operational best practice - Transparency", - "guid": "93846da9-7cc3-4923-856b-22586f4a1641", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/enable-enhanced-security", + "category": "Identity and Access Management", + "checklist": "Azure AKS Review", + "guid": "1f711a74-3672-470b-b8b8-a2148d640d79", + "id": "05.01.12", + "link": "https://learn.microsoft.com/azure/aks/use-managed-identity#use-a-pre-created-kubelet-managed-identity", + "security": 1, "services": [ - "Subscriptions", - "Defender" + "AKS", + "Entra" ], - "severity": "High", - "subcategory": "Secure Score", - "text": "All subscriptions protected by Security Center are shown (no subscription filter set)" + "severity": "Medium", + "simple": -1, + "subcategory": "Identity", + "text": "For finer control consider using a managed Kubelet Identity", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "bdddea8a-487c-4deb-9861-bc3bc14aea6e", - "link": "https://learn.microsoft.com/azure/security-center/security-center-compliance-dashboard", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "cbd8ac2a-aebc-4a2a-94da-1dbf3dc99248", + "id": "06.01.01", + "link": "https://azure.github.io/application-gateway-kubernetes-ingress/setup/install-existing/", + "security": 1, "services": [ - "Defender" + "AKS", + "ACR", + "AppGW" ], - "severity": "High", - "subcategory": "Regulatory Compliance", - "text": "Compliance controls are green for any required compliance requirements" + "severity": "Medium", + "simple": -1, + "subcategory": "Best practices", + "text": "If using AGIC, do not share an AppGW across clusters", + "waf": "Reliability" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "description": "Customer Operational best practice - verify", - "guid": "65e8d9a3-aec2-418e-9436-b0736db55f57", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/remediate-vulnerability-findings-vm", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | distinct id,compliant", + "guid": "8008ae7d-7e4b-4475-a6c8-bdbf59bce65d", + "id": "06.01.02", + "link": "https://learn.microsoft.com/azure/aks/http-application-routing", + "scale": 1, "services": [ - "VM", - "Defender" + "AKS" ], "severity": "High", - "subcategory": "Azure Defender", - "text": "High severity VM vulnerabilities is zero (empty)" + "simple": -1, + "subcategory": "Best practices", + "text": "Do not use AKS Application Routing Add-On", + "waf": "Reliability" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "9603334b-df9c-4c23-918d-b61171265f4b", - "link": "https://techcommunity.microsoft.com/t5/azure-network-security/azure-firewall-manager-is-now-integrated-with-azure-security/ba-p/2228679", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | distinct id,compliant", + "guid": "7bacd7b9-c025-4a9d-a5d2-25d6bc5439d9", + "id": "06.01.03", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", + "scale": 1, "services": [ - "Firewall", - "Defender" + "AKS" ], "severity": "Medium", - "subcategory": "Firewall Manager", - "text": "Hubs are protected by an Azure Firewall" + "simple": -1, + "subcategory": "Best practices", + "text": "For Windows workloads use Accelerated Networking", + "waf": "Performance" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "description": "Customer Operational best practice - verify", - "guid": "b47a393a-0803-4272-a479-8b1578a219a4", - "link": "https://learn.microsoft.com/azure/security/fundamentals/network-best-practices", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | distinct id,compliant", + "guid": "ba7da7be-9952-4914-a384-5d997cb39132", + "id": "06.01.04", + "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", + "scale": 1, "services": [ - "VNet", - "Firewall", - "Defender" + "AKS", + "LoadBalancer" ], - "severity": "Medium", - "subcategory": "Firewall Manager", - "text": "Virtual Networks are protected by a Firewall" + "severity": "High", + "subcategory": "Best practices", + "text": "Use the standard ALB (as opposed to the basic one)", + "waf": "Reliability" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "6ceb5443-5025-4922-9442-92bb628537a5", - "link": "https://azure.microsoft.com/blog/how-azure-security-center-detects-ddos-attack-using-cyber-threat-intelligence/", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "22fbe8d6-9b40-47ef-9011-25bb1a555a6b", + "id": "06.01.05", + "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#add-a-node-pool-with-a-unique-subnet", + "security": 1, "services": [ - "Firewall", - "DDoS", - "Defender" + "AKS", + "VNet" ], "severity": "Medium", - "subcategory": "Firewall Manager", - "text": "DDoS Standard enabled" + "simple": -2, + "subcategory": "Best practices", + "text": "If using Azure CNI, consider using different Subnets for NodePools", + "waf": "Security" }, { - "category": "Defender For Cloud", - "checklist": "Azure Security Review Checklist", - "guid": "5119bf8e-8f58-4542-a7d9-cdc166cd072a", - "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started?WT.mc_id=Portal-Microsoft_Azure_Security", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "c3c39c98-6bb2-4c12-859a-114b5e3df584", + "id": "06.02.01", + "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", + "security": 1, "services": [ - "Subscriptions", - "Defender" + "AKS", + "VNet", + "Cost", + "PrivateLink" ], - "severity": "High", - "subcategory": "Coverage", - "text": "Verify that all subscriptions are covered (see pricing and settings to modify)" + "severity": "Medium", + "simple": -1, + "subcategory": "Cost", + "text": "Use Private Endpoints (preferred) or Virtual Network Service Endpoints to access PaaS services from the cluster", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "4df585ec-dce9-4793-a7bc-db3b51eb2eb0", - "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "e8a03f97-8794-468d-96a7-86d60f96c97b", + "ha": 1, + "id": "06.03.01", + "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering", "services": [ - "VM", - "VNet" + "AKS", + "VPN" ], - "severity": "High", - "subcategory": "Public IPs", - "text": "VM's with public IPs should be protected by NSG " + "severity": "Medium", + "subcategory": "HA", + "text": "If hybrid connectivity is required, use 2xER or ER+VPN for better availability", + "waf": "Reliability" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "3dda6e59-d7c8-4a2e-bb11-7d6769af669c", - "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/public-ip-addresses", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | distinct id,compliant", + "guid": "a0f61565-9de5-458f-a372-49c831112dbd", + "id": "06.04.01", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", "services": [ - "VM", - "Firewall", - "EventHubs" + "AKS" ], "severity": "High", - "subcategory": "Public IPs", - "text": "VMs with public IPs are moved behind Azure Firewall Premium" + "simple": 1, + "subcategory": "IPAM", + "text": "Choose the best CNI network plugin for your requirements (Azure CNI recommended)", + "waf": "Reliability" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "a48e5a85-f222-43ec-b8bb-12308ca5017f", - "link": "https://learn.microsoft.com/azure/virtual-network/ip-services/default-outbound-access", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "7faf12e7-0943-4f63-8472-2da29c2b1cd6", + "id": "06.04.02", + "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", + "scale": 1, "services": [ - "VM" + "AKS", + "VNet" ], "severity": "High", - "subcategory": "Public IPs", - "text": "VM's that don't need public IPs do not have public IPs (i.e. internal RDP only)" + "subcategory": "IPAM", + "text": "If using Azure CNI, size your subnet accordingly considering the maximum number of pods per node", + "waf": "Performance" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "158e3ea3-a93c-42de-9e31-65c3a87a04b7", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "22f54b29-bade-43aa-b1e8-c38ec9366673", + "id": "06.04.03", + "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", + "scale": 1, "services": [ - "VNet", - "RBAC" + "AKS" ], - "severity": "Medium", - "subcategory": "NSG", - "text": "NSG RBAC is used to restrict access to network security team" + "severity": "High", + "simple": -1, + "subcategory": "IPAM", + "text": "If using Azure CNI, check the maximum pods/node (default 30)", + "waf": "Performance" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "a209939b-da47-4778-b24c-116785c2fa55", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "description": "For internal apps organizations often open the whole AKS subnet in their firewalls. This opens network access to the nodes too, and potentially to the pods as well (if using Azure CNI). If LoadBalancer IPs are in a different subnet, only this one needs to be available to the app clients. Another reason is that if the IP addresses in the AKS subnet are a scarce resource, consuming its IP addresses for services will reduce the maximum scalability of the cluster .", + "guid": "13c00567-4b1e-4945-a459-c373e7ed6162", + "id": "06.04.04", + "link": "https://learn.microsoft.com/azure/aks/internal-lb", + "security": 1, "services": [ + "AKS", "VNet" ], - "severity": "High", - "subcategory": "NSG", - "text": "NSG Inbound security rules do not contain a * (wildcard) in Source field" + "severity": "Low", + "simple": -1, + "subcategory": "IPAM", + "text": "If using private-IP LoadBalancer services, use a dedicated subnet (not the AKS subnet)", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "b56a9480-08be-47d7-b4c4-76b6d8bdcf59", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", + "id": "06.04.05", + "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", + "scale": 1, "services": [ - "VNet" + "AKS" ], - "severity": "Medium", - "subcategory": "NSG", - "text": "NSG outbound security rules are used to control traffic to specific IP addresses for traffic not routed through a Firewall" + "severity": "High", + "subcategory": "IPAM", + "text": "Size the service IP address range accordingly (it is going to limit the cluster scalability)", + "waf": "Reliability" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "bce65de8-a13f-4988-9946-8d66a786d60f", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "57bf217f-6dc8-481c-81e2-785773e9c00f", + "id": "06.05.01", + "link": "https://learn.microsoft.com/azure/aks/use-byo-cni", + "security": 1, "services": [ - "VNet" + "AKS" ], - "severity": "High", - "subcategory": "NSG", - "text": "NSG do not have Source as a * (wildcard) in place." + "severity": "Low", + "simple": -2, + "subcategory": "Operations", + "text": "If required add your own CNI plugin", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "a6c97be9-955d-404c-9c49-c986cb2d1215", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-nsg-manage-log", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "4b3bb365-9458-44d9-9ed1-5c8f52890364", + "id": "06.05.02", + "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools", + "security": 1, "services": [ - "VNet", - "Sentinel" + "AKS" ], - "severity": "Medium", - "subcategory": "NSG", - "text": "NSG Diagnostics send NetworkSecurityGroupEvent and NetworkSecurityGroupRuleCounter traffic to Sentinel LAW" + "severity": "Low", + "simple": -2, + "subcategory": "Operations", + "text": "If required configure Public IP per node in AKS", + "waf": "Performance" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "aa124b6e-4df5-485e-adce-9793b7bcdb3b", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "b3808b9f-a1cf-4204-ad01-3a923ce474db", + "id": "06.06.01", + "link": "https://learn.microsoft.com/azure/aks/concepts-network", + "scale": 1, "services": [ - "VNet", - "RBAC" + "AKS" ], "severity": "Medium", - "subcategory": "UDR", - "text": "UDR RBAC is used to restrict access to the network security team" + "simple": -1, + "subcategory": "Scalability", + "text": "Use an ingress controller to expose web-based apps instead of exposing them with LoadBalancer-type services", + "waf": "Reliability" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "51eb2eb0-3dda-46e5-ad7c-8a2edb117d67", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "ccb534e7-416e-4a1d-8e93-533b53199085", + "id": "06.06.02", + "link": "https://learn.microsoft.com/azure/aks/nat-gateway", + "scale": 1, "services": [ - "VNet", - "Firewall" + "AKS" ], - "severity": "High", - "subcategory": "UDR", - "text": "If Zero Trust, then UDR's are used to send all traffic to the Azure Firewall Premium" + "severity": "Low", + "simple": -1, + "subcategory": "Scalability", + "text": "Use Azure NAT Gateway as outboundType for scaling egress traffic", + "waf": "Reliability" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "69af669c-a48e-45a8-9f22-23ece8bb1230", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "8ee9a69a-1b58-4b1e-9c61-476e110a160b", + "id": "06.06.03", + "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni#dynamic-allocation-of-ips-and-enhanced-subnet-support", + "scale": 1, "services": [ - "VNet" + "AKS" ], "severity": "Medium", - "subcategory": "UDR", - "text": "UDR's that do not send all traffic to AzureFirewallPremium are known and documented." + "simple": -1, + "subcategory": "Scalability", + "text": "Use Dynamic allocations of IPs in order to avoid Azure CNI IP exhaustion", + "waf": "Reliability" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "8ca5017f-158e-43ea-9a93-c2de7e3165c3", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview#default", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | distinct id,compliant", + "guid": "3b365a91-7ecb-4e48-bbe5-4cd7df2e8bba", + "id": "06.07.01", + "link": "https://learn.microsoft.com/azure/aks/limit-egress-traffic", + "security": 2, "services": [ - "VNet" + "AKS", + "NVA" ], "severity": "High", - "subcategory": "Virtual Networks", - "text": "Customer is familiar with Azure networking defaults / SDN default routing in Azure" + "simple": -2, + "subcategory": "Security", + "text": "Filter egress traffic with AzFW/NVA if your security requirements mandate it", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "description": "Customer operational best practice - verify", - "guid": "a87a04b7-a209-4939-ada4-7778f24c1167", - "link": "https://github.com/MicrosoftDocs/azure-docs/issues/53672", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | distinct id,compliant", + "guid": "c4581559-bb91-463e-a908-aed8c44ce3b2", + "id": "06.07.02", + "link": "https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges", + "security": 1, "services": [ - "VNet", - "RBAC" + "AKS" ], "severity": "Medium", - "subcategory": "Virtual Networks", - "text": "VNet RBAC is used to restrict access to the network security team" - }, - { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "85c2fa55-b56a-4948-808b-e7d7e4c476b6", - "link": "https://learn.microsoft.com/azure/virtual-network/policy-reference", + "simple": -1, + "subcategory": "Security", + "text": "If using a public API endpoint, restrict the IP addresses that can access it", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==true) | distinct id, compliant", + "guid": "ecccd979-3b6b-4cda-9b50-eb2eb03dda6d", + "id": "06.07.03", + "link": "https://learn.microsoft.com/azure/aks/private-clusters", + "security": 1, "services": [ - "VNet" + "AKS" ], "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet Security recommendations are remediated and there are no 'At-risk' VNets " + "simple": -1, + "subcategory": "Security", + "text": "Use private clusters if your requirements mandate it", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "d8bdcf59-bce6-45de-aa13-f98879468d66", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==true) | distinct id, compliant", + "guid": "ce7f2a7c-297c-47c6-adea-a6ff838db665", + "id": "06.07.04", + "link": "https://learn.microsoft.com/azure/aks/use-network-policies", + "security": 1, "services": [ - "VNet" + "AKS", + "AzurePolicy" ], - "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet Peering connections are understood and expected traffic flows are documented" + "severity": "Medium", + "simple": -1, + "subcategory": "Security", + "text": "For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used ", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "a786d60f-a6c9-47be-a955-d04c3c49c986", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-service-endpoints-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | distinct id,compliant", + "guid": "58d7c892-ddb1-407d-9769-ae669ca48e4a", + "id": "06.07.05", + "link": "https://learn.microsoft.com/azure/aks/use-network-policies", + "security": 1, "services": [ - "VNet" + "AKS", + "AzurePolicy" ], "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet Service Endpoints are in use, no legacy Public Service Endpoints exist" + "subcategory": "Security", + "text": "Enable a Kubernetes Network Policy option (Calico/Azure)", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "1f625659-ee55-480a-9824-9c931213dbd7", - "link": "https://learn.microsoft.com/azure/private-link/private-endpoint-overview", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "85e2223e-ce8b-4b12-907c-a5f16f158e3e", + "id": "06.07.06", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", + "security": 1, "services": [ - "VNet", - "PrivateLink" + "AKS", + "AzurePolicy" ], "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet Private Endpoints are in use to allow access from on-premises environments, no legacy public endpoints exist" + "simple": -1, + "subcategory": "Security", + "text": "Use Kubernetes network policies to increase intra-cluster security", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "fb012f70-943f-4630-9722-ea39d2b1ce63", - "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "a3a92c2d-e7e2-4165-a3a8-7af4a7a1f893", + "id": "06.07.07", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", + "security": 2, "services": [ - "VNet", - "Monitor" + "AKS", + "WAF" ], "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet Monitoring enabled" + "simple": -1, + "subcategory": "Security", + "text": "Use a WAF for web workloads (UIs or APIs)", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "2055b29b-ade4-4aad-8e8c-39ec94666731", - "link": "https://learn.microsoft.com/azure/virtual-network/kubernetes-network-policies", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "cost": -2, + "graph": "Resources | where type=~'microsoft.containerservice/managedclusters' | project resourceGroup,name,pools=properties.agentPoolProfiles | mv-expand pools | project subnetId=tostring(pools.vnetSubnetID) | where isnotempty(subnetId) | join (Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,enableDdosProtection=tostring(properties.enableDdosProtection),subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,enableDdosProtection,subnetId=tostring(subnets.id)) on subnetId | distinct id,resourceGroup,name,enableDdosProtection | extend compliant = (enableDdosProtection == 'true')", + "guid": "9bda4776-8f24-4c11-9775-c2ea55b46a94", + "id": "06.07.08", + "link": "https://learn.microsoft.com/azure/virtual-network/ddos-protection-overview", + "security": 2, "services": [ - "VNet", "AKS", - "AzurePolicy" + "VNet", + "DDoS" ], - "severity": "High", - "subcategory": "Virtual Networks", - "text": "Secure traffic between pods using network policies in Azure Kubernetes Service (AKS)" + "severity": "Medium", + "subcategory": "Security", + "text": "Use DDoS Standard in the AKS Virtual Network", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "3c005674-c1e9-445b-959c-373e7ed71623", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-scenario-udr-gw-nva", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "cost": -2, + "graph": "Resources | where type=~'microsoft.containerservice/managedclusters' | project resourceGroup,name,pools=properties.agentPoolProfiles | mv-expand pools | project subnetId=tostring(pools.vnetSubnetID) | where isnotempty(subnetId) | join (Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,enableDdosProtection=tostring(properties.enableDdosProtection),subnets=properties.subnets | mv-expand subnets | project id,resourceGroup,name,enableDdosProtection,subnetId=tostring(subnets.id)) on subnetId | distinct id,resourceGroup,name,enableDdosProtection | extend compliant = (enableDdosProtection == 'true')", + "guid": "6c46b91a-1107-4485-ad66-3183e2a8c266", + "id": "06.07.09", + "link": "https://learn.microsoft.com/azure/aks/http-proxy", + "security": 2, "services": [ - "VNet", - "NVA" + "AKS" ], - "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet NVA (appliances) customer follows published architecture pattern" + "severity": "Low", + "subcategory": "Security", + "text": "If required add company HTTP Proxy", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "b375a917-ecbe-448f-ae64-dd7df2e8bbbc", - "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", + "category": "Network Topology and Connectivity", + "checklist": "Azure AKS Review", + "guid": "e9855d04-c3c3-49c9-a6bb-2c12159a114b", + "id": "06.07.10", + "link": "https://learn.microsoft.com/azure/aks/servicemesh-about", + "security": 1, "services": [ - "VNet", - "Sentinel", - "Monitor" + "AKS" ], - "severity": "High", - "subcategory": "Virtual Networks", - "text": "VNet Diagnostic settings are enabled and sending VMProtectionAlerts to the Azure Sentinel LAW" + "severity": "Medium", + "simple": -2, + "subcategory": "Security", + "text": "Consider using a service mesh for advanced microservice communication management", + "waf": "Security" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "468155ab-c916-44e9-a09a-ed8c44cf3b2b", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/connectivity-to-azure", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "67f7a9ed-5b31-4f38-a3f3-9812b2463cff", + "ha": 1, + "id": "07.01.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-metric-alerts", "services": [ - "ExpressRoute", - "VPN" + "AKS", + "Monitor" ], "severity": "High", - "subcategory": "Connectivity", - "text": "Use ExpressRoute or VPN to access Azure resources from on-premises environments" + "simple": -1, + "subcategory": "Alerting", + "text": "Configure alerts on the most critical metrics (see Container Insights for recommendations)", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "bd8ac2aa-ebca-42a4-9da1-dbf3dd992481", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "337453a3-cc63-4963-9a65-22ac19e80696", + "ha": 1, + "id": "07.02.01", + "link": "https://learn.microsoft.com/azure/advisor/advisor-get-started", "services": [ - "RBAC", - "VWAN" + "AKS", + "Entra" ], - "severity": "High", - "subcategory": "Virtual WAN", - "text": "VWAN RBAC is used to restrict access to the network security team" + "severity": "Low", + "simple": -1, + "subcategory": "Compliance", + "text": "Check regularly Azure Advisor for recommendations on your cluster", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "718d1dca-1f62-4565-aee5-580a38249c93", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-global-transit-network-architecture", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "3aa70560-e7e7-4968-be3d-628af35b2ced", + "id": "07.02.03", + "link": "https://learn.microsoft.com/azure/aks/certificate-rotation", "services": [ - "VWAN", - "Monitor" + "AKS" ], - "severity": "High", - "subcategory": "Virtual WAN", - "text": "VWAN Customer is using Secure Hub or external Firewall to route and monitor traffic." + "severity": "Low", + "simple": 1, + "subcategory": "Compliance", + "text": "Enable AKS auto-certificate rotation", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "1213dbd7-fb01-42f7-8943-f6304722ea39", - "link": "https://learn.microsoft.com/azure/web-application-firewall/overview", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "e189c599-df0d-45a7-9dd4-ce32c1881370", + "id": "07.02.04", + "link": "https://learn.microsoft.com/azure/aks/supported-kubernetes-versions", + "security": 1, "services": [ - "RBAC", - "AppGW" + "AKS" ], "severity": "High", - "subcategory": "Application Gateway", - "text": "AppGW RBAC is used to restrict access to the network security team" + "simple": -1, + "subcategory": "Compliance", + "text": "Have a regular process to upgrade your kubernetes version periodically (quarterly, for example), or use the AKS autoupgrade feature", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "d2b1ce63-2055-4b29-aade-4aad1e8c39ec", - "link": "https://learn.microsoft.com/azure/application-gateway/configuration-front-end-ip", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "6f7c4c0d-4e51-4464-ad24-57ed67138b82", + "id": "07.02.05", + "link": "https://learn.microsoft.com/azure/aks/node-updates-kured", "services": [ - "EventHubs", - "AppGW", - "WAF" + "AKS" ], "severity": "High", - "subcategory": "Application Gateway", - "text": "AppGW All external facing web services are behind Application Gateways with WAF enabled " + "simple": -1, + "subcategory": "Compliance", + "text": "Use kured for Linux node upgrades in case you are not using node-image upgrade", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "94666731-3c00-4567-9c1e-945b459c373e", - "link": "https://learn.microsoft.com/azure/application-gateway/configuration-front-end-ip", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "139c9580-ade3-426a-ba09-cf157d9f6477", + "id": "07.02.06", + "link": "https://learn.microsoft.com/azure/aks/node-image-upgrade", + "security": 1, "services": [ - "EventHubs", - "AppGW", - "WAF" + "AKS" ], "severity": "High", - "subcategory": "Application Gateway", - "text": "AppGW All internal facing web services are behind Application Gateways with WAF enabled " + "simple": -1, + "subcategory": "Compliance", + "text": "Have a regular process to upgrade the cluster node images periodically (weekly, for example)", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "7ed71623-b375-4a91-9ecb-e48fbe64dd7d", - "link": "https://learn.microsoft.com/azure/application-gateway/ssl-overview", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "0102ce16-ee30-41e6-b882-e52e4621dd68", + "id": "07.02.07", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/bedrock/bedrock-automated-deployments", "services": [ - "AppGW" + "AKS" ], - "severity": "High", - "subcategory": "Application Gateway", - "text": "AppGW - External facing has TLS/SSL enabled and redirects all traffic to 443 (no port 80 traffic)" + "severity": "Low", + "subcategory": "Compliance", + "text": "Consider gitops to deploy applications or cluster configuration to multiple clusters", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "f2e8bbbc-4681-455a-ac91-64e9909aed8c", - "link": "https://learn.microsoft.com/azure/frontdoor/", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "d7672c26-7602-4482-85a4-14527fbe855c", + "id": "07.02.08", + "link": "https://learn.microsoft.com/azure/aks/command-invoke", "services": [ - "FrontDoor", - "RBAC" + "AKS" ], - "severity": "High", - "subcategory": "FrontDoor", - "text": "Front Door RBAC is used to restrict access to the network security team" + "severity": "Low", + "subcategory": "Compliance", + "text": "Consider using AKS command invoke on private clusters", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "44cf3b2b-3818-4baf-a2cf-2149d013a923", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/front-door-security-baseline?toc=/azure/frontdoor/TOC.json", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "31d7aaab-7571-4449-ab80-53d89e89d17b", + "id": "07.02.09", + "link": "https://learn.microsoft.com/azure/aks/node-auto-repair#node-autodrain", + "security": 1, "services": [ - "FrontDoor", - "AzurePolicy", - "WAF" + "AKS" ], - "severity": "High", - "subcategory": "FrontDoor", - "text": "Front Door is associated with a WAF policy" + "severity": "Low", + "subcategory": "Compliance", + "text": "For planned events consider using Node Auto Drain", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "ce574dcc-bd8a-4c2a-aebc-a2a44da1dbf3", - "link": "https://learn.microsoft.com/azure/frontdoor/front-door-custom-domain-https", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "ed0fda7f-211b-47c7-8b6e-c18873fb473c", + "id": "07.02.10", + "link": "https://learn.microsoft.com/azure/aks/faq", + "security": 1, "services": [ - "FrontDoor", - "AzurePolicy" + "AKS" ], "severity": "High", - "subcategory": "FrontDoor", - "text": "Front Door TLS/SSL policy is configured" + "subcategory": "Compliance", + "text": "Develop own governance practices to make sure no changes are performed by operators in the node RG (aka 'infra RG')", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "dd992481-718d-41dc-a1f6-25659ee5580a", - "link": "https://learn.microsoft.com/azure/frontdoor/front-door-url-redirect", + "category": "Operations", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | distinct id,compliant", + "guid": "73b32a5a-67f7-4a9e-b5b3-1f38c3f39812", + "id": "07.02.11", + "link": "https://learn.microsoft.com/azure/aks/cluster-configuration", "services": [ - "FrontDoor" + "AKS" ], - "severity": "High", - "subcategory": "FrontDoor", - "text": "Front Door redirect port 80 to port 443 is configured (listeners)" + "severity": "Low", + "simple": 1, + "subcategory": "Compliance", + "text": "Use custom Node RG (aka 'Infra RG') name", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "38249c93-1213-4dbd-9fb0-12f70943f630", - "link": "https://learn.microsoft.com/azure/frontdoor/front-door-diagnostics", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "b2463cff-e189-4c59-adf0-d5a73dd4ce32", + "ha": 1, + "id": "07.02.12", + "link": "https://kubernetes.io/docs/setup/release/notes/", "services": [ - "FrontDoor", - "Sentinel" + "AKS" ], - "severity": "High", - "subcategory": "FrontDoor", - "text": "Front Door diagnostics logs send ApplicationGatewayAccessLog &ApplicationGateway FirewallLog to Sentinel LAW" + "severity": "Medium", + "simple": -1, + "subcategory": "Compliance", + "text": "Do not use deprecated Kubernetes APIs in your YAML manifests", + "waf": "Operations" }, { - "category": "Azure Networking", - "checklist": "Azure Security Review Checklist", - "guid": "4722ea39-d2b1-4ce6-9205-5b29bade4aad", - "link": "https://learn.microsoft.com/azure/security/fundamentals/ddos-best-practices", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "c1881370-6f7c-44c0-b4e5-14648d2457ed", + "ha": 1, + "id": "07.02.13", + "link": "https://learn.microsoft.com/azure-stack/aks-hci/adapt-apps-mixed-os-clusters", "services": [ - "DDoS" + "AKS" ], - "severity": "High", - "subcategory": "DDOS Protection", - "text": "Enabled for Firewall public IP's (all public IPs)" + "severity": "Low", + "simple": -1, + "subcategory": "Compliance", + "text": "Taint Windows nodes", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "346ad56f-bdb8-44db-8bcd-0a689af63f1e", - "link": "https://learn.microsoft.com/security/compass/identity#a-single-enterprise-directory", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "67138b82-0102-4ce1-9ee3-01e6e882e52e", + "id": "07.02.14", + "link": "https://learn.microsoft.com/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-20H2%2Cwindows-10-20H2", "services": [ - "Entra" + "AKS" ], - "severity": "High", - "subcategory": "Tenant", - "text": "Establish a single enterprise directory for managing identities of full-time employees and enterprise resources." + "severity": "Low", + "subcategory": "Compliance", + "text": "Keep windows containers patch level in sync with host patch level", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "a46108cd-6a76-4749-ae69-b7bf61410010", - "link": "https://learn.microsoft.com/security/compass/identity#synchronized-identity-systems", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "description": "Via Diagnostic Settings at the cluster level", + "guid": "5b56ad48-408f-4e72-934c-476ba280dcf5", + "ha": 1, + "id": "07.02.15", + "link": "https://learn.microsoft.com/azure/aks/monitor-aks", "services": [ - "Entra" + "AKS", + "Monitor" ], - "severity": "High", - "subcategory": "Tenant", - "text": "Synchronize your cloud identity with your existing identity systems." + "severity": "Low", + "subcategory": "Compliance", + "text": "Send master logs (aka API logs) to Azure Monitor or your preferred log management solution", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "a1ab96ceb-c149-4ce2-bcad-3bd375ebfc7f", - "link": "https://learn.microsoft.com/security/compass/identity#cloud-provider-identity-source-for-third-parties", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "64d1a846-e28a-4b6b-9a33-22a635c15a21", + "id": "07.02.16", + "link": "https://learn.microsoft.com/azure/aks/node-pool-snapshot", "services": [ - "Entra" + "AKS" ], - "severity": "High", - "subcategory": "Tenant", - "text": "Use cloud identity services to host non-employee accounts such as vendors, partners, and customers, rather than rather than including them in your on-premises directory." + "severity": "Low", + "subcategory": "Compliance", + "text": "If required use nodePool snapshots", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "343473ec-ed5c-49e1-98f4-cb09524a23cd", - "link": "https://learn.microsoft.com/security/compass/identity#block-legacy-authentication", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "c5a5b252-1e44-4a59-a9d2-399c4d7b68d0", + "id": "07.03.01", + "link": "https://learn.microsoft.com/azure/aks/spot-node-pool", "services": [ - "Entra" + "AKS", + "Cost" ], - "severity": "High", - "subcategory": "Tenant", - "text": "Disable insecure legacy protocols for internet-facing services." + "severity": "Low", + "simple": -1, + "subcategory": "Cost", + "text": "Consider spot node pools for non time-sensitive workloads", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "70dceb23-50c7-4d8d-bf53-8cc104c7dc44", - "link": "https://learn.microsoft.com/azure/security/fundamentals/identity-management-best-practices#enable-single-sign-on", + "category": "Operations", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==true) | distinct id,compliant", + "guid": "c755562f-2b4e-4456-9b4d-874a748b662e", + "id": "07.03.02", + "link": "https://learn.microsoft.com/azure/aks/concepts-scale", + "scale": 1, "services": [ - "Entra" + "AKS", + "Cost" ], - "severity": "High", - "subcategory": "Tenant", - "text": "Enable single sign-on" + "severity": "Low", + "simple": -1, + "subcategory": "Cost", + "text": "Consider AKS virtual node for quick bursting", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "87791be1-1eb0-48ed-8003-ad9bcf241b99", - "link": "https://learn.microsoft.com/security/compass/identity#no-on-premises-admin-accounts-in-cloud-identity-providers", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "6f8389a7-f82c-4b8e-a8c0-aa63a25a4956", + "ha": 1, + "id": "07.04.01", + "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", "services": [ - "Entra" + "AKS", + "Monitor" ], "severity": "High", - "subcategory": "Privileged administration", - "text": "Don’t synchronize accounts with the highest privilege access to on-premises resources as you synchronize your enterprise identity systems with cloud directories." + "simple": -1, + "subcategory": "Monitoring", + "text": "Monitor your cluster metrics with Container Insights (or other tools like Prometheus)", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "9e6efe9d-f28f-463b-9bff-b5080173e9fe", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices#5-limit-the-number-of-global-administrators-to-less-than-5", + "category": "Operations", + "checklist": "Azure AKS Review", + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==true) | distinct id,compliant", + "guid": "eaa8dc4a-2436-47b3-9697-15b1752beee0", + "ha": 1, + "id": "07.04.02", + "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", "services": [ - "Entra" + "AKS", + "Monitor" ], "severity": "High", - "subcategory": "Privileged administration", - "text": "Limit the number of Global Administrators to less than 5" + "simple": -1, + "subcategory": "Monitoring", + "text": "Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch)", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "e0d968d3-87f6-41fb-a4f9-d852f1673f4c", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices#6-use-groups-for-azure-ad-role-assignments-and-delegate-the-role-assignment", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "4621dd68-c5a5-4be2-bdb1-1726769ef669", + "ha": 1, + "id": "07.04.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-analyze", "services": [ - "RBAC", - "Entra" + "AKS", + "Monitor" ], - "severity": "High", - "subcategory": "Privileged administration", - "text": "Use groups for Azure AD role assignments and delegate the role assignment" + "severity": "Medium", + "simple": -1, + "subcategory": "Monitoring", + "text": "Monitor CPU and memory utilization of the nodes", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "00350863-4df6-4050-9cf1-cbaa6d58283e", - "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-admins#managed-accounts-for-admins", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "1a4835ac-9422-423e-ae80-b123081a5417", + "ha": 1, + "id": "07.04.04", + "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", "services": [ - "Entra", - "AzurePolicy" + "AKS", + "Monitor" ], - "severity": "High", - "subcategory": "Privileged administration", - "text": "Ensure all critical impact admins are managed by enterprise directory to follow organizational policy enforcement." + "severity": "Medium", + "simple": -1, + "subcategory": "Monitoring", + "text": "If using Azure CNI, monitor % of pod IPs consumed per node", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "eae64d01-0d3a-4ae1-a89d-cc1c2ad3888f", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices#4-configure-recurring-access-reviews-to-revoke-unneeded-permissions-over-time", + "category": "Operations", + "checklist": "Azure AKS Review", + "description": "I/O in the OS disk is a critical resource. If the OS in the nodes gets throttled on I/O, this could lead to unpredictable behavior, typically ending up in node being declared NotReady", + "guid": "415833ea-3ad3-4c2d-b733-165c3acbe04b", + "ha": 1, + "id": "07.04.05", + "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance", "services": [ - "Entra" + "Monitor", + "Storage", + "EventHubs", + "ServiceBus", + "AKS" ], - "severity": "High", - "subcategory": "Privileged administration", - "text": "Configure recurring access reviews to revoke unneeded permissions over time" + "severity": "Medium", + "simple": -1, + "subcategory": "Monitoring", + "text": "Monitor OS disk queue depth in nodes", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "922ac19f-916d-4697-b8ea-ded26bdd186f", - "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-admins#admin-workstation-security", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "be209d39-fda4-4777-a424-d116785c2fa5", + "ha": 1, + "id": "07.04.06", + "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", "services": [ - "Entra", - "Monitor" + "AKS", + "Monitor", + "LoadBalancer", + "NVA" ], "severity": "Medium", - "subcategory": "Privileged administration", - "text": "Ensure critical impact admins use a workstation with elevated security protections and monitoring" + "simple": -1, + "subcategory": "Monitoring", + "text": "If not using egress filtering with AzFW/NVA, monitor standard ALB allocated SNAT ports", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "1e8c39ec-9466-4673-83c0-05674c1e945b", - "link": "https://learn.microsoft.com/azure/active-directory/external-identities/compare-with-b2c", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "74c2ee76-569b-4a79-a57e-dedf91b022c9", + "ha": 1, + "id": "07.04.07", + "link": "https://learn.microsoft.com/azure/aks/aks-resource-health", "services": [ - "Entra" + "AKS", + "Monitor" ], - "severity": "High", - "subcategory": "External Identities", - "text": "Identity Providers: Verify external identity providers are known" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Subscribe to resource health notifications for your AKS cluster", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "459c373e-7ed7-4162-9b37-5a917ecbe48f", - "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "b54eb2eb-03dd-4aa3-9927-18e2edb11726", + "ha": 1, + "id": "07.05.01", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", "services": [ - "Entra" + "AKS" ], "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Guest user access set to 'Guest user access is restricted?'" + "simple": -1, + "subcategory": "Resources", + "text": "Configure requests and limits in your pod specs", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "be64dd7d-f2e8-4bbb-a468-155abc9164e9", - "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "769ef669-1a48-435a-a942-223ece80b123", + "ha": 1, + "id": "07.05.02", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", "services": [ - "RBAC", - "Entra" + "AKS" ], - "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Guest invite settings set to 'Only users assigned to specific admin roles'" + "severity": "Medium", + "simple": -1, + "subcategory": "Resources", + "text": "Enforce resource quotas for namespaces", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "909aed8c-44cf-43b2-a381-8bafa2cf2149", - "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "081a5417-4158-433e-a3ad-3c2de733165c", + "id": "07.05.03", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "services": [ - "Entra" + "AKS", + "Subscriptions" ], "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Enable guest self-service sign up via flows set to 'Disabled' " + "subcategory": "Resources", + "text": "Ensure your subscription has enough quota to scale out your nodepools", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "d013a923-ce57-44dc-abd8-ac2aaebca2a4", - "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | distinct id,compliant", + "guid": "90ce65de-8e13-4f9c-abd4-69266abca264", + "ha": 1, + "id": "07.06.01", + "link": "https://learn.microsoft.com/azure/aks/concepts-scale", "services": [ - "Entra" + "AKS" ], - "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Collaboration restrictions set to 'Allow invitations to the specified domains'" + "severity": "Medium", + "subcategory": "Scalability", + "text": "Use the Cluster Autoscaler", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "4da1dbf3-dd99-4248-8718-d1dca1f62565", - "link": "https://learn.microsoft.com/azure/active-directory/governance/deploy-access-reviews", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "graph": "where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | distinct id,compliant", + "guid": "831c2872-c693-4b39-a887-a561bada49bc", + "ha": 1, + "id": "07.06.02", + "link": "https://learn.microsoft.com/azure/aks/custom-node-configuration", "services": [ - "Entra" + "AKS" ], - "severity": "Medium", - "subcategory": "External Identities", - "text": "Access Reviews: Enabled for all groups" + "severity": "Low", + "subcategory": "Scalability", + "text": "Customize node configuration for AKS node pools", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "9ee5580a-3824-49c9-9121-3dbd7fb012f7", - "link": "https://learn.microsoft.com/azure/active-directory/manage-apps/configure-user-consent", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "faa19bfe-9d55-4d04-a3c4-919ca1b2d121", + "id": "07.06.03", + "link": "https://learn.microsoft.com/azure/aks/concepts-scale", + "scale": 1, "services": [ - "Entra" + "AKS" ], "severity": "Medium", - "subcategory": "Enterprise Applications", - "text": "Consent & Permissions: Allow user consent for apps from verified publishers" + "simple": -1, + "subcategory": "Scalability", + "text": "Use the Horizontal Pod Autoscaler when required", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "0943f630-4722-4ea3-ad2b-1ce632055b29", - "link": "https://learn.microsoft.com/azure/active-directory/manage-apps/configure-user-consent-groups", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "description": "Larger nodes will bring higher performance and features such as ephemeral disks and accelerated networking, but they will increase the blast radius and decrease the scaling granularity", + "guid": "5ae124ba-34df-4585-bcdc-e9bd3bb0cdb3", + "id": "07.06.04", + "link": "https://blog.cloudtrooper.net/2020/10/23/which-vm-size-should-i-choose-as-aks-node/", "services": [ - "Entra" + "AKS" ], - "severity": "Medium", - "subcategory": "Enterprise Applications", - "text": "Consent & Permissions: Allow group owner consent for selected group owners " + "severity": "High", + "subcategory": "Scalability", + "text": "Consider an appropriate node size, not too large or too small", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "bade4aad-1e8c-439e-a946-667313c00567", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy-configure-custom-domain", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "38800e6a-ae01-40a2-9fbc-ae5a06e5462d", + "id": "07.06.05", + "link": "https://learn.microsoft.com/azure/aks/quotas-skus-regions#service-quotas-and-limits", "services": [ - "Entra" + "AKS" ], - "severity": "High", - "subcategory": "Custom Domains", - "text": "Only validated customer domains are registered" + "severity": "Low", + "subcategory": "Scalability", + "text": "If more than 5000 nodes are required for scalability then consider using an additional AKS cluster", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "4c1e945b-459c-4373-b7ed-71623b375a91", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/tutorial-enable-sspr", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "9583c0f6-6083-43f6-aa6b-df7102c901bb", + "id": "07.06.06", + "link": "https://learn.microsoft.com/azure/event-grid/event-schema-aks", "services": [ - "Entra", - "AzurePolicy" + "AKS" ], - "severity": "High", - "subcategory": "Password Reset", - "text": "Self-service password reset policy requirement verified compliant." + "severity": "Low", + "subcategory": "Scalability", + "text": "Consider subscribing to EventGrid Events for AKS automation", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "7ecbe48f-be64-4dd7-bf2e-8bbbc468155a", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/howto-sspr-deployment", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "c5016d8c-c6c9-4165-89ae-673ef0fff19d", + "id": "07.06.07", + "link": "https://learn.microsoft.com/azure/aks/manage-abort-operations", "services": [ - "Entra" + "AKS" ], - "severity": "Medium", - "subcategory": "Password Reset", - "text": "Set number of days before users are asked to re-confirm authentication information is not set to zero" + "severity": "Low", + "subcategory": "Scalability", + "text": "For long running operation on an AKS cluster consider event termination", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "bc9164e9-909a-4ed8-a44c-f3b2b3818baf", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/howto-sspr-deployment", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "c4e37133-f186-4ce1-aed9-9f1b32f6e021", + "id": "07.06.08", + "link": "https://learn.microsoft.com/azure/aks/use-azure-dedicated-hosts", "services": [ - "Entra" + "AKS" ], - "severity": "High", - "subcategory": "Password Reset", - "text": "Set number of methods required to reset password are selected" + "severity": "Low", + "subcategory": "Scalability", + "text": "If required consider using Azure Dedicated Hosts for AKS nodes", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "a2cf2149-d013-4a92-9ce5-74dccbd8ac2a", - "link": "https://learn.microsoft.com/azure/active-directory/roles/delegate-app-roles", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "graph": "where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | mvexpand pools | extend compliant = (pools.osDiskType=='Ephemeral') | project id,name=strcat(name,'-',pools.name), resourceGroup, compliant", + "guid": "24367b33-6971-45b1-952b-eee0b9b588de", + "id": "07.07.01", + "link": "https://learn.microsoft.com/azure/aks/cluster-configuration", + "scale": 1, "services": [ - "Entra" + "AKS", + "Storage" ], "severity": "High", - "subcategory": "User Setting", - "text": "Disable 'Users can register applications'" + "subcategory": "Storage", + "text": "Use ephemeral OS disks", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "aebca2a4-4da1-4dbf-9dd9-92481718d1dc", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/users-default-permissions", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", + "id": "07.07.02", + "link": "https://learn.microsoft.com/azure/virtual-machines/disks-types", + "scale": 1, "services": [ - "Entra" + "AKS", + "Storage" ], "severity": "High", - "subcategory": "User Setting", - "text": "Restrict access to Administrative portal (portal.azure.com) to administrators only" + "subcategory": "Storage", + "text": "For non-ephemeral disks, use high IOPS and larger OS disks for the nodes when running many pods/node since it requires high performance for running multiple pods and will generate huge logs with default AKS log rotation thresholds", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "a1f62565-9ee5-4580-a382-49c931213dbd", - "link": "https://learn.microsoft.com/azure/active-directory/enterprise-users/linkedin-integration", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "39c486ce-d5af-4062-89d5-18bb5fd795db", + "id": "07.07.03", + "link": "https://learn.microsoft.com/azure/aks/use-ultra-disks", + "scale": 1, "services": [ - "Entra" + "AKS", + "Storage" ], - "severity": "High", - "subcategory": "User Setting", - "text": "Disable 'LinkedIn account connection'" + "severity": "Low", + "subcategory": "Storage", + "text": "For hyper performance storage option use Ultra Disks on AKS", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "7fb012f7-0943-4f63-8472-2ea39d2b1ce6", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-monitoring", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "9f7547c1-747d-4c56-868a-714435bd19dd", + "ha": 1, + "id": "07.07.04", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", "services": [ - "Sentinel", - "Entra", - "Monitor" + "AKS", + "Storage", + "SQL" ], - "severity": "High", - "subcategory": "Diagnostic Settings", - "text": "Enabled and send to Log Analytics workspace with Sentinel" + "severity": "Medium", + "simple": -1, + "subcategory": "Storage", + "text": "Avoid keeping state in the cluster, and store data outside (AzStorage, AzSQL, Cosmos, etc)", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "21e44a19-a9dd-4399-afd7-b28dc8355562", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-deployment-plan", + "category": "Operations", + "checklist": "Azure AKS Review", + "cost": -1, + "guid": "24429eb7-2281-4376-85cc-57b4a4b18142", + "id": "07.07.05", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-storage", + "scale": 1, "services": [ - "Entra" + "AKS", + "Storage" ], - "severity": "High", - "subcategory": "PIM enabled", - "text": "Privileged Identity Management enabled" + "severity": "Medium", + "subcategory": "Storage", + "text": "If using AzFiles Standard, consider AzFiles Premium and/or ANF for performance reasons", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "46f4389a-7f42-4c78-b78c-06a63a21a495", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/just-in-time-access-usage?tabs=jit-config-asc%2Cjit-request-asc", + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "83958a8c-2689-4b32-ab57-cfc64546135a", + "ha": 1, + "id": "07.07.06", + "link": "https://learn.microsoft.com/azure/aks/availability-zones#azure-disk-availability-zone-support", "services": [ - "Entra" + "AKS", + "Storage" ], - "severity": "High", - "subcategory": "PIM enabled", - "text": "Implement 'just in time' (JIT) access to further lower the exposure time for privileged accounts (reduce standing access)" + "severity": "Medium", + "simple": -1, + "subcategory": "Storage", + "text": "If using Azure Disks and AZs, consider having nodepools within a zone for LRS disk with VolumeBindingMode:WaitForFirstConsumer for provisioning storage in right zone or use ZRS disk for nodepools spanning multiple zones", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "6e6a8dc4-a20e-427b-9e29-711b1352beee", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/concept-conditional-access-policy-common", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "Define a resource group structure for placement of Azure Arc-enabled servers resources", + "guid": "585e1112-9bd7-4ba0-82f7-b94ef6e043d2", "services": [ - "Entra", - "AzurePolicy" + "Arc" ], "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Configure conditional access policies / Access Controls" + "subcategory": "Capacity Planning", + "text": "One or more resource groups is required for onboarding servers into Azure", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "079b588d-efc4-4972-ac3c-d21bf77036e5", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/location-condition", + "category": "Foundation", + "checklist": "Azure Arc Review", + "guid": "aa359271-8e6e-4205-8725-769e46691e88", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", "services": [ "Entra", - "AzurePolicy" + "Arc" ], "severity": "Medium", - "subcategory": "Conditional Access Policies", - "text": "Conditions: Restricted Locations" + "subcategory": "Capacity Planning", + "text": "Take Azure Active Directory object limitations into account", + "waf": "Performance" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "e6b4bed3-d5f3-4547-a134-7dc56028a71f", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/tutorial-enable-azure-mfa", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "The following resource providers needs to be registered: Microsoft.HybridCompute, Microsoft.GuestConfiguration, Microsoft.HybridConnectivity", + "guid": "deace4bb-1deb-44c6-9fc3-fc14eeaa3692", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-resource-providers", "services": [ - "Entra", - "AzurePolicy" + "Subscriptions", + "Arc" ], "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: MFA enabled for all users" + "subcategory": "General", + "text": "Has the Resource providers required been registered in all subscriptions", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "fe1bd15d-d2f0-4d5e-972d-41e3611cc57b", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-admin-mfa", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "Aligning with an existing or creating an Azure tagging strategy is recommended. Resource tags allow you to quickly locate it, automate operational tasks amd more. ", + "guid": "c6d37331-65c7-4acb-b44b-be609d79f2e8", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/", "services": [ - "Entra", - "AzurePolicy" + "Arc" ], - "severity": "Medium", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Require MFA for Administrators" + "severity": "Low", + "subcategory": "General", + "text": "Has a tagging strategy for Azure Arc-enabled servers been defined", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "4a4b1410-d439-4589-ac22-89b3d6b57cfc", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-azure-management", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "Installation of the connected machine agent is supported on most newer Windows and Linux operative systems, review the link to se the latest list", + "guid": "7778424c-5167-475c-9fa9-5b96ad88408e", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#supported-operating-systems", "services": [ - "Entra", - "AzurePolicy" + "Arc" ], "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Require MFA for Azure Management " + "subcategory": "General", + "text": "What operating systems need to be Azure Arc-enabled", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "645461e1-a3e3-4453-a3c8-639637a552d6", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/howto-conditional-access-policy-block-legacy", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "There are software requirements to the agent installation. Some might require a system reboot after installation, review to link", + "guid": "372734b8-76ba-428f-8145-901365d38e53", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#software-requirements", "services": [ - "Entra", - "AzurePolicy" + "Arc" ], "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Block Legacy Protocols" + "subcategory": "General", + "text": "Are required software installed on Windows and Linux servers to support the installation", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "7ae9eab4-0fd3-4290-998b-c178bdc5a06c", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/require-managed-devices", + "category": "Foundation", + "checklist": "Azure Arc Review", + "guid": "d44c7c89-19ca-41f6-b521-5ae514ba34d4", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/?products=azure-arc®ions=all", "services": [ - "Entra", - "AzurePolicy" + "Arc" ], "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Require devices to be marked as compliant" + "subcategory": "General", + "text": "Make sure to use a supported Azure region", + "waf": "Reliability" }, { - "category": "Identity", - "checklist": "Azure Security Review Checklist", - "description": "Customer documented policy", - "guid": "a7144351-e19d-4d34-929e-b7228137a151", - "link": "https://devblogs.microsoft.com/premier-developer/azure-active-directory-automating-guest-user-management/", + "category": "Foundation", + "checklist": "Azure Arc Review", + "description": "The scope include organization into management groups, subscriptions, and resource groups.", + "guid": "f9ccbd86-8266-4abc-a264-f9a19bf39d95", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/organize-inventory-servers#organize-resources-with-built-in-azure-hierarchies", "services": [ - "Entra", - "AzurePolicy" + "Subscriptions", + "Arc" ], - "severity": "Medium", - "subcategory": "Guest users", - "text": "Is there a policy to track guest user accounts (i.e. usage/delete/disable)?" + "severity": "Low", + "subcategory": "Organization", + "text": "Define the structure for Azure management of resources", + "waf": "Performance" }, { "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "c5bb4e4f-1814-4287-b5ca-8c26c9b32ab5", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/identity-secure-score", + "checklist": "Azure Arc Review", + "description": "Define RBAC rules to the servers / resource groups as required for servers management, the 'Azure Connected Machine Resource Administrator' or 'Hybrid Server Resource Administrator' role would be sufficient for management of the Azure Arc-enabled servers resources in Azure", + "guid": "9bf39d95-d44c-47c8-a19c-a1f6d5215ae5", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#identity-and-access-control", "services": [ - "Entra" + "RBAC", + "Entra", + "Arc" ], - "severity": "High", - "subcategory": "Identity Secure Score", - "text": "Implement Identity Secure Score based on best practices in your industry" + "severity": "Medium", + "subcategory": "Access", + "text": "Assign RBAC rights to Azure AD user/group access for managing Azure Arc-enabled servers", + "waf": "Security" }, { "category": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "bcfc6998-a135-4e33-9897-e31c67d68cb6", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", + "checklist": "Azure Arc Review", + "guid": "14ba34d4-585e-4111-89bd-7ba012f7b94e", + "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-nonaad", "services": [ + "AKV", "Entra", - "AzurePolicy" + "Arc" ], - "severity": "Medium", - "subcategory": "Break Glass Accounts", - "text": "At least two break glass accounts have been created and policy around their use exists" + "severity": "Low", + "subcategory": "Access", + "text": "Consider using managed identities for applications to access Azure resources like Key Vault example in link", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "0ac252b9-99a6-48af-a7c9-a8f821b8eb8c", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "An Azure subscription must be parented to the same Azure AD tenant", + "guid": "35ac9322-23e1-4380-8523-081a94174158", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#azure-subscription-and-service-limits", "services": [ - "VM", - "AzurePolicy" + "Subscriptions", + "Entra", + "Arc" ], "severity": "High", - "subcategory": "Access Control", - "text": "Control VM Access leveraging Azure Policy" + "subcategory": "Requirements", + "text": "An Azure Active Directory tenant must be available with at least one subscription", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "0aa77e26-e4d5-4aea-a8dc-4e2436bc336d", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/templates/syntax", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Users (or SPs) need the 'Azure Connected Machine Onboarding' or 'Contributor' role to onboarding of servers", + "guid": "33ee7ad6-c6d3-4733-865c-7acbe44bbe60", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", "services": [ - "VM" + "RBAC", + "Entra", + "Arc" ], "severity": "Medium", - "subcategory": "Access Control", - "text": "Reduce variability in your setup and deployment of VMs by leveraging templates" + "subcategory": "Requirements", + "text": "Define which users (AAD user/groups) has access to onboard Azure Arc-enabled servers", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "b5945bda-4333-44fd-b91c-234182b65275", - "link": "https://learn.microsoft.com/windows-server/identity/ad-ds/plan/security-best-practices/implementing-least-privilege-administrative-models", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Ensure to only add the rights to users or groups that is required to perform their role", + "guid": "9d79f2e8-7778-4424-a516-775c6fa95b96", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", "services": [ - "VM" + "RBAC", + "Entra", + "Arc" ], "severity": "Medium", - "subcategory": "Access Control", - "text": "Secure privileged access to deploy VMS by reducing who has access to Resources through Governance" + "subcategory": "Security", + "text": "Use the principle of least privileged", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "269440b4-be3d-43e0-a432-76d4bdc015bc", - "link": "https://learn.microsoft.com/azure/architecture/checklist/resiliency-per-service", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "A service principle with the 'Azure Connected Machine Onboarding' role is required for at-scale onboarding of servers, consider more SP's if onboarding is done by different teams/decentralized management", + "guid": "ad88408e-3727-434b-a76b-a28f21459013", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-service-principal#create-a-service-principal-for-onboarding-at-scale", "services": [ - "VM" + "RBAC", + "Entra", + "Arc" ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Use multiple VMs for your workloads for better availability " + "subcategory": "Security", + "text": "How many Service Principals are needed for onboarding Arc-enabled servers into Azure", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "f219e4a1-eb58-4879-935d-227886d30b66", - "link": "https://learn.microsoft.com/azure/backup/backup-azure-vms-first-look-arm", + "category": "Identity", + "checklist": "Azure Arc Review", + "description": "Consider assigning the rights for the 'Azure Connected Machine Onboarding' role at the resource group level, to control the resource creation", + "guid": "65d38e53-f9cc-4bd8-9826-6abca264f9a1", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/prerequisites#required-permissions", "services": [ - "VM", - "ASR" + "RBAC", + "Entra", + "Arc" ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Deploy and test a disaster recovery solution " + "subcategory": "Security", + "text": "Limit the rights to onboard Azure Arc-enabled servers to the desired resource groups", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "c57be595-1900-4838-95c5-86cb291ec16a", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability-set-overview", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Plan for agent deployments at scale", + "guid": "6ee79d6b-5c2a-4364-a4b6-9bad38aad53c", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment", "services": [ - "VM" + "Monitor", + "Arc" ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Availability sets" + "subcategory": "Management", + "text": "Define a strategy for agent provisioning", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "1d076ef9-f141-4acd-ae57-9377bcdb3751", - "link": "https://learn.microsoft.com/azure/availability-zones/az-overview?context=/azure/virtual-machines/context/context", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Use Microsoft Update to ensure that the connected machine agent is always up-to-date", + "guid": "c78e1d76-6673-457c-9496-74c5ed85b859", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#upgrade-the-agent", "services": [ - "VM" + "Monitor", + "Arc" ], - "severity": "Medium", - "subcategory": "High Availability ", - "text": "Availability Zones" + "severity": "High", + "subcategory": "Management", + "text": "Define a strategy for agent updates", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "ab2ac1fa-d66e-415d-9d5a-2adb2c3e2326", - "link": "https://learn.microsoft.com/azure/architecture/resiliency/recovery-loss-azure-region", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Recommendation is to use Azure Policy, or another automation tool like Azure DevOps - important is to avoid configuration drift.", + "guid": "c7733be2-a1a2-47b7-95a9-1be1f388ff39", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-vm-extensions", "services": [ - "VM" + "Monitor", + "AzurePolicy", + "Arc" ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Regional fault tolerance " + "subcategory": "Management", + "text": "Define a strategy for extension installation", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "af225ca4-4e16-496f-bdde-ace4cb1deb4c", - "link": "https://learn.microsoft.com/azure/security/fundamentals/antimalware", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Use automatic upgrades where available and define an update strategy for all extensions not supporting automatic upgrades.", + "guid": "4c2bd463-cbbb-4c86-a195-abb91a4ed90d", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-automatic-vm-extension-upgrade?tabs=azure-portal", "services": [ - "VM" + "Monitor", + "Arc" ], "severity": "High", - "subcategory": "Protect against malware", - "text": "Install antimalware solutions" + "subcategory": "Management", + "text": "Define a strategy for extension updates", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "650c3fc1-4eeb-4b36-a382-9e3eec218368", - "link": "https://learn.microsoft.com/azure/security-center/security-center-partner-integration", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Azure Automanage help implement Microsoft best-practices for servers management in Azure", + "guid": "7a927c39-74d1-4102-aac6-aae01e6a84de", + "link": "https://learn.microsoft.com/azure/automanage/automanage-arc", "services": [ - "VM", - "Defender" + "Monitor", + "Arc" ], - "severity": "High", - "subcategory": "Protect against malware", - "text": "Integrate antimalware solution with Security Center" + "severity": "Medium", + "subcategory": "Management", + "text": "Consider using Azure Automanage to control settings and avoid configuration drift on servers", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "7a0177a2-b594-45bd-a433-34fdf91c2341", - "link": "https://learn.microsoft.com/azure/automation/update-management/overview", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "37b6b780-cbaf-4e6c-9658-9d457a927c39", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", "services": [ - "VM" + "Monitor", + "Arc" ], "severity": "High", - "subcategory": "Manage VM Updates", - "text": "Keep VMs up to date using Update Management with Azure Automation" + "subcategory": "Monitoring", + "text": "Monitor for unresponsive agents", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "c6fa96b9-6ad8-4840-af37-2734c876ba28", - "link": "https://learn.microsoft.com/azure/virtual-machines/automatic-vm-guest-patching", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "74d1102c-ac6a-4ae0-8e6a-84de5df47d2d", + "link": "https://learn.microsoft.com/azure/azure-monitor/agents/log-analytics-agent#data-collected", "services": [ - "VM" + "Monitor", + "Arc" ], "severity": "Medium", - "subcategory": "Manage VM Updates", - "text": "Ensure Windows images for deployment have the most recent level of updates " + "subcategory": "Monitoring", + "text": "Design a monitoring strategy to send metrics and logs to an Log Analytics workspace", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "02145901-465d-438e-9309-ccbd979266bc", - "link": "https://learn.microsoft.com/azure/security-center/asset-inventory", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "92881b1c-d5d1-4e54-a296-59e3958fd782", + "link": "https://learn.microsoft.com/azure/service-health/resource-health-alert-monitor-guide", "services": [ - "VM", - "Defender" + "Monitor", + "Arc" ], - "severity": "High", - "subcategory": "Manage VM Updates", - "text": "Rapidly apply security updates to VMs using Microsoft Defender for Cloud" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use notification in Activity logs to receive notification on unexpected changes to the resources", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "ca274faa-19bf-439d-a5d4-4c7c8919ca1f", - "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "89c93555-6d02-4bfe-9564-b0d834a34872", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/learn/tutorial-enable-vm-insights", "services": [ - "VM" + "Monitor", + "Arc" ], - "severity": "High", - "subcategory": "Encrypt your VHDs", - "text": "Enable encryption on your VMs" + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Monitor for compliance and operational monitoring", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "6d5315ae-524b-4a34-b458-5e12139bd7bb", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/disk-encryption-key-vault#set-up-a-key-encryption-key-kek", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "guid": "5df47d2d-9288-41b1-ad5d-1e54a29659e3", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/plan-at-scale-deployment#phase-3-manage-and-operate", "services": [ - "VM" + "Monitor", + "Arc" ], - "severity": "High", - "subcategory": "Encrypt your VHDs", - "text": "Add Key Encryption Key (KEK) for added layer of security for encryption " + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Create an alert to identify Azure Arc-enabled servers that aren't using the latest version of the Azure connected machine agent", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "012f7b95-e06e-4154-b2aa-3592828e6e20", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/snapshot-copy-managed-disk", + "category": "Management and Monitoring", + "checklist": "Azure Arc Review", + "description": "Use Update Management in Azure Automation or the new Update Management Center (preview) functionality to ensure update management of servers", + "guid": "ae2cc84c-37b6-4b78-8cba-fe6c46589d45", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/hybrid/server/best-practices/arc-update-management", "services": [ - "VM", - "LoadBalancer" + "Monitor", + "Arc" ], - "severity": "Medium", - "subcategory": "Encrypt your VHDs", - "text": "Take a snapshot of disks before encryption for rollback purposes" + "severity": "Low", + "subcategory": "Security", + "text": "Use Azure Arc-enabled servers to control software updates deployments to servers", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "5173676a-e466-491e-a835-ad942223e138", - "link": "https://learn.microsoft.com/azure/role-based-access-control/built-in-roles", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "The Connected Machine Agent will by default communicate with Azure services over public Internet connectivity using HTTPS (TCP port 443)", + "guid": "f6e043d2-aa35-4927-88e6-e2050725769e", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#details", "services": [ - "VM", - "Entra" + "Arc" ], "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Ensure only the central networking group has permissions to networking resources " + "subcategory": "Networking", + "text": "Define a connectivity method from the server to Azure", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "10523081-a941-4741-9833-ff7ad7c6d373", - "link": "https://learn.microsoft.com/azure/security-center/security-center-partner-integration", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "The Connected Machine Agent can be configured to use a proxy server, it is recommended to define the proxy server address using 'azcmagent config set proxy.url' command on the local system.", + "guid": "46691e88-35ac-4932-823e-13800523081a", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/manage-agent#update-or-remove-proxy-settings", "services": [ - "VM", - "Entra" + "Arc" ], - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Identity and remediate exposed VMs that allow access from 'ANY' source IP address" + "severity": "Medium", + "subcategory": "Networking", + "text": "Is a proxy server a required for communication over the Public Internet", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "75a91be1-f388-4f03-a4d2-cd463cbbbc86", - "link": "https://learn.microsoft.com/azure/security-center/security-center-just-in-time", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "The Connected Machine Agent can use a Private Link for communication with Azure Services over an existing ExpressRoute or VPN connection", + "guid": "94174158-33ee-47ad-9c6d-3733165c7acb", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/private-link-security", + "services": [ + "ExpressRoute", + "VPN", + "PrivateLink", + "Arc" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Is a private (not public Internet) connection required?", + "waf": "Operations" + }, + { + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "Firewall configuration might be required for the agent to communicate with Azure, use the link to see ServiceTags and/or URL's required", + "guid": "e44bbe60-9d79-4f2e-a777-8424c516775c", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#service-tags", "services": [ - "VM" + "Arc" ], "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Restrict management ports (RDP, SSH) using Just-in-Time Access" + "subcategory": "Networking", + "text": "Will Firewall configurations be needed in order to ensure communication with Azure Services?", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "8295abc9-1a4e-4da0-bae2-cc84c47b6b78", - "link": "http://learn.microsoft.com/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "Use available automation tool for the system in question to regularly update the Azure endpoints", + "guid": "6fa95b96-ad88-4408-b372-734b876ba28f", + "link": "https://www.microsoft.com/download/details.aspx?id=56519", "services": [ - "VM" + "Arc" ], - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Remove internet access and implement jump servers for RDP" + "severity": "Low", + "subcategory": "Networking", + "text": "Can the Firewall or Proxy rules be automated updated if Service Tags or IP addresses change", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "1cbafe6c-4658-49d4-98a9-27c3974d1102", - "link": "https://learn.microsoft.com/azure/vpn-gateway/vpn-gateway-about-forced-tunneling", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "Configure Servers to use Transport Layer Security (TLS) version 1.2", + "guid": "21459013-65d3-48e5-9f9c-cbd868266abc", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/network-requirements?tabs=azure-cloud#transport-layer-security-12-protocol", "services": [ - "VM", - "VPN" + "Arc" ], "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Remove direct logging into servers using RDP/SSH from internet and implement VPN or express route" + "subcategory": "Networking", + "text": "Always use secure communication for Azure where possible", + "waf": "Security" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "dad6aae1-1e6b-484e-b5df-47d2d92881b1", - "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", + "category": "Networking", + "checklist": "Azure Arc Review", + "description": "All extensions (like log analytics etc.) have separate network requirements, be sure to include all in the network design.", + "guid": "a264f9a1-9bf3-49d9-9d44-c7c8919ca1f6", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/hybrid/arc-enabled-servers/eslz-arc-servers-connectivity#define-extensions-connectivity-method", "services": [ - "VM", - "Bastion" + "Monitor", + "PrivateLink", + "Arc" ], - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Leverage Azure Bastion as your RDP/SSH broker for added security and reduction in footprint" + "severity": "Low", + "subcategory": "Networking", + "text": "Include communication for Azure Arc-enabled Servers extensions in the design (firewall/proxy/private link)", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "cd5d1e54-a297-459e-9968-0e78289c9356", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "ac6aae01-e6a8-44de-9df4-7d2d92881b1c", + "link": "https://learn.microsoft.com/azure/governance/policy/", "services": [ - "Sentinel", - "Monitor" + "AzurePolicy", + "Arc" ], - "severity": "High", - "subcategory": "Architecture ", - "text": "All tenants contain have Sentinel enabled on at least one Log Analytics workspace" + "severity": "Medium", + "subcategory": "Management", + "text": "Use Azure Policy to implement a governance model for hybrid connected servers", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "57d02bff-4564-4b0d-a34a-359836ee79d6", - "link": "https://learn.microsoft.com/azure/sentinel/best-practices-workspace-architecture", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "5c2a3649-4b69-4bad-98aa-d53cc78e1d76", + "link": "https://learn.microsoft.com/azure/governance/machine-configuration/overview", "services": [ - "Sentinel" + "Arc" ], - "severity": "High", - "subcategory": "Architecture ", - "text": "Customer understands Sentinel architecture" + "severity": "Medium", + "subcategory": "Management", + "text": "Consider using Machine configurations for in guest OS configurations", + "waf": "Operations" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "e8f5c586-c7d9-4cdc-86ac-c075ef9b141a", - "link": "https://learn.microsoft.com/azure/sentinel/multiple-workspace-view", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "667357c4-4967-44c5-bd85-b859c7733be2", + "link": "https://learn.microsoft.com/azure/governance/machine-configuration/machine-configuration-create", "services": [ - "ACR", - "Sentinel", - "Monitor" + "AzurePolicy", + "Arc" ], "severity": "Medium", - "subcategory": "Architecture ", - "text": "Customer knows how to monitor Incidents across multiple Sentinel instances" + "subcategory": "Management", + "text": "Evaluate the need for custom Guest Configuration policies", + "waf": "Operations" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "8989579e-76b8-497e-910a-7da7be9966e1", - "link": "https://learn.microsoft.com/azure/sentinel/manage-soc-with-incident-metrics", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "49674c5e-d85b-4859-a773-3be2a1a27b77", + "link": "https://learn.microsoft.com/azure/automation/change-tracking/overview", "services": [ - "Sentinel" + "Monitor", + "Arc" ], "severity": "Medium", - "subcategory": "Overview", - "text": "No Incidents open more than 24 hours" + "subcategory": "Monitoring", + "text": "Consider using change tracking for tracking changes made on the servers", + "waf": "Operations" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "5d3c4ada-97cb-43d1-925a-b225c6f4e068", - "link": "https://learn.microsoft.com/azure/sentinel/whats-new", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "d5d1e54a-2965-49e3-a58f-d78289c93555", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/data-residency", "services": [ - "Sentinel" + "Arc" ], - "severity": "Low", - "subcategory": "News & Guides", - "text": "Customer have been shown the News & Guides tab" + "severity": "Medium", + "subcategory": "Requirements", + "text": "Make sure to use an Azure region for storing the metadata approved by the organization", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "5edddea8-a4b7-4cde-a4c6-1fc3fc14eea6", - "link": "https://learn.microsoft.com/azure/sentinel/enable-entity-behavior-analytics", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "195abb91-a4ed-490d-ae2c-c84c37b6b780", + "link": "https://learn.microsoft.com/azure/key-vault/general/basic-concepts", "services": [ - "Sentinel" + "AKV", + "Arc" ], "severity": "Medium", - "subcategory": "UEBA ", - "text": "UEBA Configured (Sentinel/Settings/Settings/Configure UEBA)" + "subcategory": "Secrets", + "text": "Use Azure Key Vault for certificate management on servers", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "e69d8d9a-3eec-4218-b687-ab077adb49e5", - "link": "https://learn.microsoft.com/azure/sentinel/connect-azure-active-directory", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Consider using a short-lived Azure AD service principal client secrets.", + "guid": "6d02bfe4-564b-40d8-94a3-48726ee79d6b", + "link": "https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret", "services": [ + "AKV", + "Storage", "Entra", - "Sentinel" + "Arc" ], "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Active Directory in configured and 'Last Log Received' shows today" + "subcategory": "Secrets", + "text": "What is the acceptable life time of the secret used by SP's", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "b9603334-fdf8-4cc2-9318-db61171269f4", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#azure-active-directory-identity-protection", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "A private key is saved to the disk, ensure this is protected using disk encryption", + "guid": "a1a27b77-5a91-4be1-b388-ff394c2bd463", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#using-disk-encryption", "services": [ - "Entra", - "Sentinel" + "AKV", + "Arc" ], - "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Active Directory Identity Protection is configured and 'Last Log Received' shows today" + "severity": "Medium", + "subcategory": "Secrets", + "text": "Secure the public key for Azure Arc-enabled Servers", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "0b4aa3d3-e070-4327-9d4b-98b15b8a219a", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#azure-activity", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Local administrator is required to install the Connected Machine Agent on Windows and Linux systems", + "guid": "29659e39-58fd-4782-a9c9-35556d02bfe4", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/onboard-portal#install-manually", "services": [ - "Sentinel" + "Arc" ], "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Activity is configured is configured and 'Last Log Received' shows today" + "subcategory": "Security", + "text": "Ensure there is local administrator access for executing the agent installation", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "8e13f9cc-bd46-4826-9abc-a264f9a19bfe", - "link": "https://learn.microsoft.com/azure/sentinel/connect-defender-for-cloud", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Members of the local administrator group on Windows and users with root privileges on Linux, have permissions to manage the agent via command line.", + "guid": "564b0d83-4a34-4872-9ee7-9d6b5c2a3649", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#agent-security-and-permissions", "services": [ - "Sentinel", - "Defender" + "Arc" ], - "severity": "High", - "subcategory": "Data Connectors", - "text": "Microsoft Defender for Cloud is configured and 'Last Log Received' shows today" + "severity": "Medium", + "subcategory": "Security", + "text": "Limit the amount of users with local administrator rights to the servers", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "9d55d04c-3c49-419c-a1b2-d1215ae114b9", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#azure-firewall", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "4b69bad3-8aad-453c-a78e-1d76667357c4", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/managed-identity-authentication", "services": [ - "Firewall", - "Sentinel" + "Entra", + "Arc" ], - "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Firewall is configured and 'Last Log Received' shows today" + "severity": "Medium", + "subcategory": "Security", + "text": "Consider using and restricting access to managed identities for applications.", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "34df585e-cccd-49bd-9ba0-cdb3b54eb2eb", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#windows-firewall", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "description": "Use Defender for Endpoint or another AV and EDR solution to protect endpoints", + "guid": "5a91be1f-388f-4f39-9c2b-d463cbbbc868", + "link": "https://learn.microsoft.com/azure/security-center/security-center-get-started", "services": [ - "Sentinel" + "Defender", + "Arc" ], - "severity": "High", - "subcategory": "Data Connectors", - "text": "Windows Firewall is configured and 'Last Log Received' shows today" + "severity": "Medium", + "subcategory": "Security", + "text": "Enable Defender for Servers for all servers to secure hybrid workloads from threats", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "03ddaa25-9271-48d2-bdb1-0725769ef669", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference#windows-security-events-via-ama", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "cbafe6c4-6589-4d45-9a92-7c3974d1102c", "services": [ - "Sentinel" + "Arc" ], - "severity": "High", - "subcategory": "Data Connectors", - "text": "Security Events is configured with AMA and 'Last Log Received' shows today" + "severity": "Medium", + "subcategory": "Security", + "text": "Define controls to detect security misconfigurations and track compliance", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "1a4834ac-9322-423e-ae80-b123081a5417", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "cbbbc868-195a-4bb9-8a4e-d90dae2cc84c", + "link": "https://learn.microsoft.com/azure/azure-arc/servers/security-overview#extension-allowlists-and-blocklists", "services": [ - "Sentinel" + "Arc" ], - "severity": "High", - "subcategory": "Data Connectors", - "text": "Security Events - verify Azure computers are connected and sending data to the workspace" + "severity": "Medium", + "subcategory": "Security", + "text": "Use allow- or block-lists to control what extensions can be installed on the Azure Arc-enabled servers", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "859c773e-7e26-4162-9b77-5a917e1f348e", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "41177955-fe8f-430b-ae72-20dc5b6880da", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/overview", "services": [ - "Sentinel" + "Entra" ], "severity": "High", - "subcategory": "Data Connectors", - "text": "Security Events - verify non-Azure computers are connected and sending data to the workspace" + "subcategory": "Business", + "text": "Understand what kind of solution you're creating, such as business-to-business (B2B), business-to-consumer (B2C), or your enterprise software, and how tenants are different from users." }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "f354c27d-42e8-4bba-a868-155abb9163e9", - "link": "https://learn.microsoft.com/azure/sentinel/connect-aws?tabs=s3", - "services": [ - "Sentinel" - ], + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "2d33d1b7-697c-49f9-b944-afbeac0b2c8f", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", + "services": [], "severity": "High", - "subcategory": "Data Connectors", - "text": "Connector for AWS" + "subcategory": "Business", + "text": "Define your tenants. Understand how many tenants you will support initially, and your growth plans." }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "909ae28c-84c3-43b6-a780-8bafe6c42149", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", - "services": [ - "Sentinel" - ], + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "a2111b8b-cc66-4aa2-9da6-c09fa23851b6", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/pricing-models", + "services": [], "severity": "High", - "subcategory": "Data Connectors", - "text": "Connector for GCP" + "subcategory": "Business", + "text": "Define your pricing model and ensure it aligns with your tenants' consumption of Azure resources." }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "d413a923-c357-44d1-8028-ac6aae01e6a8", - "link": "https://learn.microsoft.com/azure/sentinel/detect-threats-built-in", - "services": [ - "Sentinel" - ], - "severity": "High", - "subcategory": "Analytics Rules", - "text": "Customer has enabled Analytics rules and configured Incidents " + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "331e84a6-2d65-4359-92ff-a1870b062995", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/pricing-models", + "services": [], + "severity": "Medium", + "subcategory": "Business", + "text": "Understand whether you need to separate your tenants into different tiers. Tiers might have different pricing, features, performance promises, geographic locations, and so forth." }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "4de5df43-d299-4248-8718-d5d1e5f62565", - "link": "https://azure.microsoft.com/updates/controlling-data-volume-and-retention-in-log-analytics-2/", - "services": [ - "Sentinel" - ], + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "90516b37-aab1-46ca-95bb-cc14a6a1608b", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", + "services": [], "severity": "Medium", - "subcategory": "Settings", - "text": "Customer does not have a daily cap enabled" + "subcategory": "Business", + "text": "Based on your customers' requirements, decide on the tenancy models that are appropriate for various parts of your solution." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "9e3558fd-7724-49c9-9111-2d027fe412f7", - "link": "https://learn.microsoft.com/azure/firewall/premium-features", + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "f5d76ae1-7048-4ff5-abba-f1ca799578b9", + "link": "https://learn.microsoft.com/azure/marketplace/plan-saas-offer", "services": [ - "Firewall" + "Entra" ], + "severity": "Medium", + "subcategory": "Business", + "text": "When you're ready, sell your B2B multitenant solution using the Microsoft Commercial Marketplace." + }, + { + "category": "Reliability", + "checklist": "Multitenant architecture", + "guid": "9e7cedd9-1e05-4aeb-a7b3-01fe695a394c", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/design-checklist", + "services": [], "severity": "High", - "subcategory": "Configuration", - "text": "Azure Firewall Premium deployed" + "subcategory": "Reliability", + "text": "Review the Azure Well-Architected Reliability checklist, which is applicable to all workloads." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "4dc74a74-8b66-433a-b2a0-916a764980ad", - "link": "https://learn.microsoft.com/azure/firewall/tutorial-firewall-deploy-portal#create-a-default-route", - "services": [ - "Firewall" - ], + "category": "Reliability", + "checklist": "Multitenant architecture", + "guid": "e9521a55-2a7c-425c-8f3e-c38fd0c4df75", + "link": "https://learn.microsoft.com/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor", + "services": [], "severity": "High", - "subcategory": "Configuration", - "text": "Quad zero/force tunning enabled through Azure Firewall" + "subcategory": "Reliability", + "text": "Understand the Noisy Neighbor antipattern. Prevent individual tenants from impacting the system's availability for other tenants." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "0e278ee2-93c1-4bc3-92ba-aab7571849ab", - "link": "https://techcommunity.microsoft.com/t5/azure-network-security/role-based-access-control-for-azure-firewall/ba-p/2245598", - "services": [ - "Firewall", - "RBAC" - ], + "category": "Reliability", + "checklist": "Multitenant architecture", + "guid": "2b99cb00-9abb-49b6-b11c-f2af9692f09e", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/overview", + "services": [], "severity": "Medium", - "subcategory": "Access Control", - "text": "RBAC set to enable only authorized users" + "subcategory": "Reliability", + "text": "Design your multitenant solution for the level of growth that you expect. But don't overengineer for unrealistic growth." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "8093dc9f-c9d1-4bb7-9b36-a5a67fbb9ed5", - "link": "https://learn.microsoft.com/azure/firewall/firewall-diagnostics", - "services": [ - "Firewall", - "Monitor" - ], + "category": "Reliability", + "checklist": "Multitenant architecture", + "guid": "7a634a0e-1c9d-42b1-aac2-5a5378f103f1", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/business-metrics", + "services": [], "severity": "Medium", - "subcategory": "Diagnostic Settings", - "text": "Diagnostics enabled and sending metrics to a Log Analytics workspace " + "subcategory": "Reliability", + "text": "Define service-level objectives (SLOs) and optionally service-level agreements (SLAs) for your solution. SLAs and SLOs should be based on the requirements of your tenants, as well as the composite SLA of the Azure resources in your architecture." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "b35478c3-4798-416b-8863-cffe1cac599e", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", - "services": [ - "VNet", - "Firewall" - ], + "category": "Reliability", + "checklist": "Multitenant architecture", + "guid": "45beeeaf-fc59-4079-8fca-65d5724abaa7", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Hubs and virtual networks are protected or connected through Firewall Premium" + "subcategory": "Reliability", + "text": "Test the scale of your solution. Ensure that it performs well under all levels of load, and that it scales correctly as the number of tenants increases." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "f0d5a73d-d4de-436c-8c81-770afbc4c0e4", - "link": "https://techcommunity.microsoft.com/t5/azure-network-security/role-based-access-control-for-azure-firewall/ba-p/2245598", - "services": [ - "Firewall", - "RBAC", - "AzurePolicy" - ], + "category": "Reliability", + "checklist": "Multitenant architecture", + "guid": "2ff55551-984b-4606-95eb-bfb9c8b36761", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", + "services": [], + "severity": "Medium", + "subcategory": "Reliability", + "text": "Apply chaos engineering principles to test the reliability of your solution." + }, + { + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "8238c038-8eb2-4a02-8bd5-4908c9442c1c", + "link": "https://learn.microsoft.com/security/zero-trust", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Access controls are configured (RBAC)" + "subcategory": "Security", + "text": "Apply the Zero Trust and least privilege principles in all layers of your solution." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "5c3a87af-4a79-41f8-a39b-da47768e14c1", - "link": "https://learn.microsoft.com/azure/firewall-manager/policy-overview", + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "92160e00-6894-4102-97e0-615d4ed93c01", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/map-requests", "services": [ - "Firewall", - "AzurePolicy" + "Entra" ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Parent policy is configured " + "subcategory": "Security", + "text": "Ensure that you can correctly map user requests to tenants. Consider including the tenant context as part of the identity system, or by using another means, like application-level tenant authorization." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "15675c1e-a55b-446a-a48f-f8ae7d7e4b47", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", - "services": [ - "Firewall", - "AzurePolicy" - ], + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "3c1538b4-5676-4b85-b451-432befb37b4f", + "link": "https://learn.microsoft.com/azure/security/fundamentals/pen-testing", + "services": [], + "severity": "Medium", + "subcategory": "Security", + "text": "Perform ongoing penetration testing and security code reviews." + }, + { + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "5fca45ce-cf2d-42c0-a62c-aac92ba31498", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/governance-compliance", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Rule collections are defined" + "subcategory": "Security", + "text": "Understand your tenants' compliance requirements, including data residency and any compliance or regulatory standards that they require you to meet." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "5b6c8bcb-f59b-4ce6-9de8-a03f97879468", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "30adb90d-83d4-4a2e-986e-327ffe04e7a5", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/domain-names", "services": [ - "Firewall", - "AzurePolicy" + "DNS" ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: DNAT policies are defined" + "subcategory": "Security", + "text": "Correctly manage domain names and avoid vulnerabilities like dangling DNS and subdomain takeover attacks." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "d66a786d-60e9-46c9-9ad8-855d04c2b39c", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "72ded36d-c633-4e0d-bd41-799a29da3481", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/service/overview", + "services": [], + "severity": "Medium", + "subcategory": "Security", + "text": "Follow service-specific guidance for multitenancy." + }, + { + "category": "Cost Optimization", + "checklist": "Multitenant architecture", + "guid": "db30a9fc-9b1d-40f3-ab90-01f6a3e87fc8", + "link": "https://learn.microsoft.com/azure/architecture/framework/cost/design-checklist", "services": [ - "Firewall", - "AzurePolicy" + "Cost" ], - "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Network rules are defined" + "severity": "Medium", + "subcategory": "Cost Optimization", + "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "986bb2c1-2149-4a11-9b5e-3df574ecccd9", - "link": "https://learn.microsoft.com/azure/firewall/features", + "category": "Cost Optimization", + "checklist": "Multitenant architecture", + "guid": "8533af39-52f6-45b6-a9c3-81b2a54a31e0", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/measure-consumption", "services": [ - "Firewall", - "AzurePolicy" + "Cost" ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Application rules are defined" + "subcategory": "Cost Optimization", + "text": "Ensure you can adequately measure per-tenant consumption and correlate it with your infrastructure costs." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "793a6bcd-a3b5-40eb-8eb0-3dd95d58d7c8", - "link": "https://learn.microsoft.com/azure/firewall/dns-details", + "category": "Cost Optimization", + "checklist": "Multitenant architecture", + "guid": "c851fd44-7cf1-459c-95a4-f6455d75a981", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/cost-management-allocation", "services": [ - "Firewall", - "DNS" + "Monitor", + "Cost" ], "severity": "Medium", - "subcategory": "Firewall Manager", - "text": "DNS: Feature understood and applied or not applied" + "subcategory": "Cost Optimization", + "text": "Avoid antipatterns. Antipatterns include failing to track costs, tracking costs with unnecessary precision, real-time measurement, and using monitoring tools for billing." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "d622f54b-29ba-4de3-aad1-e8c28ec93666", - "link": "https://learn.microsoft.com/azure/firewall-manager/threat-intelligence-settings", - "services": [ - "Firewall" - ], + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "0d475a5a-2c0f-47ab-b1e1-701da68d3407", + "link": "https://learn.microsoft.com/azure/architecture/checklist/data-ops", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Threat Intelligence: Set to Alert & Deny" + "subcategory": "Operational Excellence", + "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "7313b005-674b-41e9-94a4-59c373e7ed61", - "link": "https://learn.microsoft.com/azure/firewall-manager/threat-intelligence-settings#allowlist-addresses", + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "9f7fa7a9-47fc-4f04-81f6-9f9e87571ed3", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenant-lifecycle", + "services": [], + "severity": "Medium", + "subcategory": "Operational Excellence", + "text": "Use automation to manage the tenant lifecycle, such as onboarding, deployment, provisioning, and configuration." + }, + { + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "e0bfceed-4f4e-492d-b9f5-898815faa363", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/updates", + "services": [], + "severity": "Medium", + "subcategory": "Operational Excellence", + "text": "Find the right balance for deploying service updates. Consider both your tenants' requirements and your own operational requirements." + }, + { + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "a3f80518-d428-4c02-b2cc-dfaef47db7e2", "services": [ - "Firewall" + "Monitor" ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Threat Intelligence: Allowed list (justify if they are being used - ie performance)" + "subcategory": "Operational Excellence", + "text": "Monitor the health of the overall system, as well as each tenant." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "623b365a-917e-4cbe-98eb-d54cd7df2e8b", - "link": "https://learn.microsoft.com/azure/firewall/premium-certificates", + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "dfb42da5-f871-4953-9e5c-da6fda3f1411", "services": [ - "Firewall" + "Monitor" ], + "severity": "Medium", + "subcategory": "Operational Excellence", + "text": "Configure and test alerts to notify you when specific tenants are experiencing issues or are exceeding their consumption limits." + }, + { + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "c0c72a1b-e34d-4b3d-b808-2e49f51ce47e", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/resource-organization", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "TLS enabled" + "subcategory": "Operational Excellence", + "text": "Organize your Azure resources for isolation and scale." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "bac35715-59ab-4915-9e99-08aed8c44ce3", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", - "services": [ - "Firewall" - ], + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "c5c5e22d-4b51-4cac-a980-f7aac1a4b427", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/deployment-configuration", + "services": [], + "severity": "Medium", + "subcategory": "Operational Excellence", + "text": "Avoid deployment and configuration antipatterns. Antipatterns include running separate versions of the solution for each tenant, hardcoding tenant-specific configurations or logic, and manual deployments." + }, + { + "category": "Performance Efficiency", + "checklist": "Multitenant architecture", + "guid": "f0b1fbd8-689c-4ab3-be1d-ad7607d2fbfd", + "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/performance-efficiency", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "IDPS enabled" + "subcategory": "Performance Efficiency", + "text": "Review the Azure Well-Architected Performance Efficiency checklist, which is applicable to all workloads." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "b2b3808b-9fa1-4cf1-849d-003a923ce474", - "link": "https://learn.microsoft.com/azure/firewall/snat-private-range", - "services": [ - "Firewall" - ], + "category": "Performance Efficiency", + "checklist": "Multitenant architecture", + "guid": "18911c4c-934c-49a8-839a-60c092afce30", + "link": "https://learn.microsoft.com/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor", + "services": [], "severity": "High", - "subcategory": "Firewall Manager", - "text": "SNAT: Configured " + "subcategory": "Performance Efficiency", + "text": "If you use shared infrastructure, plan for how you'll mitigate Noisy Neighbor concerns. Ensure that one tenant can't reduce the performance of the system for other tenants." }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "dbcbd8ac-2aae-4bca-8a43-da1dae2cc992", - "link": "https://learn.microsoft.com/azure/security/fundamentals/ddos-best-practices", + "category": "Performance Efficiency", + "checklist": "Multitenant architecture", + "guid": "6acf7eb5-24a3-47c7-ae87-1196cd96048e", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", "services": [ - "Firewall", - "DDoS" + "Storage" ], "severity": "Medium", - "subcategory": "DDOS Protection", - "text": "Enabled for Firewall public IP's" + "subcategory": "Performance Efficiency", + "text": "Determine how you'll scale your compute, storage, networking, and other Azure resources to match the demands of your tenants." + }, + { + "category": "Performance Efficiency", + "checklist": "Multitenant architecture", + "guid": "ea55400d-f97d-45aa-b71b-34224bf91ed4", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/resource-organization", + "services": [], + "severity": "High", + "subcategory": "Performance Efficiency", + "text": "Consider each Azure resource's scale limits. Organize your resources appropriately, in order to avoid resource organization antipatterns. For example, don't over-architect your solution to work within unrealistic scale requirements." } ], "metadata": { "name": "Master checklist", - "timestamp": "November 15, 2023" + "timestamp": "November 21, 2023" }, "severities": [ { diff --git a/checklists/network_appdelivery_checklist.en.json b/checklists/network_appdelivery_checklist.en.json index ff7e346e8..fc4f0b962 100644 --- a/checklists/network_appdelivery_checklist.en.json +++ b/checklists/network_appdelivery_checklist.en.json @@ -449,6 +449,6 @@ "metadata": { "name": "Azure Application Delivery Networking", "state": "GA", - "timestamp": "November 07, 2023" + "timestamp": "November 21, 2023" } -} +} \ No newline at end of file diff --git a/checklists/network_appdelivery_checklist.es.json b/checklists/network_appdelivery_checklist.es.json index 29f7d91c8..6912baf34 100644 --- a/checklists/network_appdelivery_checklist.es.json +++ b/checklists/network_appdelivery_checklist.es.json @@ -11,7 +11,7 @@ "id": "A01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Si usa certificados TLS administrados por el cliente con Azure Front Door, use la versión de certificado \"más reciente\". Reduzca el riesgo de interrupciones causadas por la renovación manual de certificados.", "waf": "Operaciones" }, @@ -33,7 +33,7 @@ "id": "A01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: App Gateway", "text": "Asegúrese de que usa la SKU de Application Gateway v2", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Seguridad" @@ -45,19 +45,19 @@ "id": "A01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Load Balancer", "text": "Asegúrese de que usa la SKU estándar para Azure Load Balancers", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", - "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", "id": "A01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", - "text": "Las puertas de enlace de aplicaciones deben implementarse en subredes con prefijos IP iguales o mayores que /26", + "subcategory": "Entrega de aplicaciones: App Gateway", + "text": "Application Gateways v2 debe implementarse en subredes con prefijos IP iguales o mayores que /24", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Seguridad" }, @@ -68,7 +68,7 @@ "id": "A01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: App Gateway", "text": "Implemente Azure Application Gateway v2 o aplicaciones virtuales de red de asociados que se usan para proxy de conexiones HTTP(S) entrantes dentro de la red virtual de la zona de aterrizaje y con las aplicaciones que están protegiendo.", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Seguridad" @@ -79,18 +79,42 @@ "id": "A01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: App Gateway", "text": "Use una red DDoS o planes de protección IP para todas las direcciones IP públicas en las zonas de aterrizaje de la aplicación.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", "id": "A01.08", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "severity": "Medio", + "subcategory": "Entrega de aplicaciones: App Gateway", + "text": "Configure el escalado automático con una cantidad mínima de instancias de dos.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Fiabilidad" + }, + { + "category": "Topología y conectividad de red", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", + "id": "A01.09", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", + "severity": "Medio", + "subcategory": "Entrega de aplicaciones: App Gateway", + "text": "Implementación de Application Gateway en zonas de disponibilidad", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Fiabilidad" + }, + { + "category": "Topología y conectividad de red", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use Azure Front Door con directivas de WAF para entregar y ayudar a proteger aplicaciones HTTP/S globales que abarcan varias regiones de Azure.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Seguridad" @@ -98,7 +122,7 @@ { "category": "Topología y conectividad de red", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", - "id": "A01.09", + "id": "A01.11", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -110,10 +134,10 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "A01.10", + "id": "A01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Traffic Manager", "text": "Use el Administrador de tráfico para entregar aplicaciones globales que abarquen protocolos distintos de HTTP/S.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Fiabilidad" @@ -121,7 +145,7 @@ { "category": "Topología y conectividad de red", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "A01.11", + "id": "A01.13", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Bajo", "subcategory": "Entrega de aplicaciones", @@ -132,7 +156,7 @@ { "category": "Topología y conectividad de red", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "A01.12", + "id": "A01.14", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -145,10 +169,10 @@ "category": "Topología y conectividad de red", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "A01.13", + "id": "A01.15", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Implemente los perfiles de WAF para Front Door en modo \"Prevención\".", "waf": "Seguridad" }, @@ -156,10 +180,10 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "A01.14", + "id": "A01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Evite combinar Azure Traffic Manager y Azure Front Door.", "waf": "Seguridad" }, @@ -167,40 +191,40 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "A01.15", + "id": "A01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use el mismo nombre de dominio en Azure Front Door y en su origen. Los nombres de host no coincidentes pueden causar errores sutiles.", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "A01.16", + "id": "A01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "Bajo", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Deshabilite los sondeos de estado cuando solo haya un origen en un grupo de orígenes de Azure Front Door.", "waf": "Rendimiento" }, { "category": "Topología y conectividad de red", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "A01.17", + "id": "A01.19", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Seleccione puntos de conexión de sondeo de estado correctos para Azure Front Door. Considere la posibilidad de crear puntos de conexión de estado que comprueben todas las dependencias de la aplicación.", "waf": "Fiabilidad" }, { "category": "Topología y conectividad de red", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "A01.18", + "id": "A01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "Bajo", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use sondeos de estado de HEAD con Azure Front Door para reducir el tráfico que Front Door envía a la aplicación.", "waf": "Rendimiento" }, @@ -209,10 +233,10 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "A01.19", + "id": "A01.21", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Load Balancer", "text": "Use Azure NAT Gateway en lugar de reglas de salida de Load Balancer para mejorar la escalabilidad de SNAT", "waf": "Fiabilidad" }, @@ -220,20 +244,20 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "A01.20", + "id": "A01.22", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use certificados TLS administrados con Azure Front Door. Reduzca los costos operativos y el riesgo de interrupciones debido a las renovaciones de certificados.", "waf": "Operaciones" }, { "category": "Topología y conectividad de red", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "A01.21", + "id": "A01.23", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Defina la configuración de WAF de Azure Front Door como código. Mediante el uso de código, puede adoptar más fácilmente nuevas versiones del conjunto de reglas y obtener protección adicional.", "waf": "Operaciones" }, @@ -241,20 +265,20 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "A02.01", + "id": "A01.24", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use TLS de un extremo a otro con Azure Front Door. Use TLS para las conexiones de los clientes a Front Door y de Front Door al origen.", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "A02.02", + "id": "A01.25", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use el redireccionamiento de HTTP a HTTPS con Azure Front Door. Apoye a los clientes más antiguos redirigiéndolos automáticamente a una solicitud HTTPS.", "waf": "Seguridad" }, @@ -262,10 +286,10 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "A02.03", + "id": "A01.26", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Habilite el WAF de Azure Front Door. Proteja su aplicación de una variedad de ataques.", "waf": "Seguridad" }, @@ -273,10 +297,10 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "A02.04", + "id": "A01.27", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Ajuste el WAF de Azure Front Door para su carga de trabajo. Reduzca las detecciones de falsos positivos.", "waf": "Seguridad" }, @@ -284,10 +308,10 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "A02.05", + "id": "A01.28", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use el modo de prevención con el WAF de Azure Front Door. El modo de prevención garantiza que el WAF bloquee las solicitudes malintencionadas.", "waf": "Seguridad" }, @@ -295,10 +319,10 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "A02.06", + "id": "A01.29", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Habilite los conjuntos de reglas predeterminados de WAF de Azure Front Door. Los conjuntos de reglas predeterminados detectan y bloquean los ataques comunes.", "waf": "Seguridad" }, @@ -306,60 +330,60 @@ "ammp": true, "category": "Topología y conectividad de red", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "A02.07", + "id": "A01.30", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "Alto", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Habilite las reglas de administración de bots de WAF de Azure Front Door. Las reglas de bots detectan bots buenos y malos.", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "A02.08", + "id": "A01.31", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use las versiones más recientes del conjunto de reglas de Azure Front Door WAF. Las actualizaciones del conjunto de reglas se actualizan periódicamente para tener en cuenta el panorama actual de amenazas.", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "A02.09", + "id": "A01.32", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Agregue limitación de velocidad al WAF de Azure Front Door. La limitación de velocidad bloquea a los clientes que envían accidental o intencionadamente grandes cantidades de tráfico en un corto período de tiempo.", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "A02.10", + "id": "A01.33", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Use un umbral alto para los límites de frecuencia de WAF de Azure Front Door. Los umbrales de límite de velocidad altos evitan el bloqueo del tráfico legítimo y, al mismo tiempo, brindan protección contra un número extremadamente alto de solicitudes que podrían abrumar su infraestructura. ", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "A02.11", + "id": "A01.34", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "Bajo", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Filtre geográficamente el tráfico mediante el WAF de Azure Front Door. Permita el tráfico solo de las regiones esperadas y bloquee el tráfico de otras regiones.", "waf": "Seguridad" }, { "category": "Topología y conectividad de red", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "A02.12", + "id": "A01.35", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "Medio", - "subcategory": "Entrega de aplicaciones", + "subcategory": "Entrega de aplicaciones: Front Door", "text": "Especifique la ubicación desconocida (ZZ) al filtrar geográficamente el tráfico con el WAF de Azure Front Door. Evite bloquear accidentalmente solicitudes legítimas cuando las direcciones IP no se puedan hacer coincidir geográficamente.", "waf": "Seguridad" } @@ -367,7 +391,7 @@ "metadata": { "name": "Azure Application Delivery Networking", "state": "GA", - "timestamp": "November 07, 2023" + "timestamp": "November 21, 2023" }, "severities": [ { diff --git a/checklists/network_appdelivery_checklist.ja.json b/checklists/network_appdelivery_checklist.ja.json index be69caa11..c47f27c87 100644 --- a/checklists/network_appdelivery_checklist.ja.json +++ b/checklists/network_appdelivery_checklist.ja.json @@ -11,7 +11,7 @@ "id": "A01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door でカスタマー マネージド TLS 証明書を使用する場合は、\"最新\" の証明書バージョンを使用します。証明書の手動更新によって引き起こされる停止のリスクを軽減します。", "waf": "オペレーションズ" }, @@ -33,7 +33,7 @@ "id": "A01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリケーション配信 - アプリケーション・ゲートウェイ", "text": "Application Gateway v2 SKU を使用していることを確認する", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "安全" @@ -45,19 +45,19 @@ "id": "A01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリ配信 - Load Balancer", "text": "Azure Load Balancer に Standard SKU を使用していることを確認する", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", - "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", "id": "A01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "中程度", - "subcategory": "アプリ配信", - "text": "アプリケーション ゲートウェイは、IP プレフィックスが /26 以上のサブネットにデプロイする必要があります", + "subcategory": "アプリケーション配信 - アプリケーション・ゲートウェイ", + "text": "Application Gateway v2 は、IP プレフィックスが /24 以上のサブネットにデプロイする必要があります", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "安全" }, @@ -68,7 +68,7 @@ "id": "A01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリケーション配信 - アプリケーション・ゲートウェイ", "text": "ランディング ゾーン仮想ネットワーク内およびそれらがセキュリティで保護しているアプリと共に、受信 HTTP(S) 接続のプロキシに使用される Azure Application Gateway v2 またはパートナーの NVA をデプロイします。", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "安全" @@ -79,18 +79,42 @@ "id": "A01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリケーション配信 - アプリケーション・ゲートウェイ", "text": "アプリケーション ランディング ゾーン内のすべてのパブリック IP アドレスに対して DDoS ネットワークまたは IP 保護プランを使用します。", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", "id": "A01.08", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "severity": "中程度", + "subcategory": "アプリケーション配信 - アプリケーション・ゲートウェイ", + "text": "最小数のインスタンスが 2 つになる自動スケーリングを構成します。", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "確実" + }, + { + "category": "ネットワークトポロジと接続性", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", + "id": "A01.09", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", + "severity": "中程度", + "subcategory": "アプリケーション配信 - アプリケーション・ゲートウェイ", + "text": "Application Gateway を複数の可用性ゾーンにデプロイする", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "確実" + }, + { + "category": "ネットワークトポロジと接続性", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door と WAF ポリシーを使用して、複数の Azure リージョンにまたがるグローバル HTTP/S アプリを配信し、保護します。", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "安全" @@ -98,7 +122,7 @@ { "category": "ネットワークトポロジと接続性", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", - "id": "A01.09", + "id": "A01.11", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "中程度", "subcategory": "アプリ配信", @@ -110,10 +134,10 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "A01.10", + "id": "A01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Traffic Manager", "text": "Traffic Manager を使用して、HTTP/S 以外のプロトコルにまたがるグローバル アプリを配信します。", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "確実" @@ -121,7 +145,7 @@ { "category": "ネットワークトポロジと接続性", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "A01.11", + "id": "A01.13", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "低い", "subcategory": "アプリ配信", @@ -132,7 +156,7 @@ { "category": "ネットワークトポロジと接続性", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "A01.12", + "id": "A01.14", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "中程度", "subcategory": "アプリ配信", @@ -145,10 +169,10 @@ "category": "ネットワークトポロジと接続性", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "A01.13", + "id": "A01.15", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Front Door の WAF プロファイルを \"防止\" モードでデプロイします。", "waf": "安全" }, @@ -156,10 +180,10 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "A01.14", + "id": "A01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Traffic Manager と Azure Front Door の組み合わせは避けてください。", "waf": "安全" }, @@ -167,40 +191,40 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "A01.15", + "id": "A01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door と配信元で同じドメイン名を使用します。ホスト名が一致しないと、微妙なバグが発生する可能性があります。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "A01.16", + "id": "A01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "低い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door 配信元グループに配信元が 1 つしかない場合は、正常性プローブを無効にします。", "waf": "パフォーマンス" }, { "category": "ネットワークトポロジと接続性", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "A01.17", + "id": "A01.19", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door に適した正常性プローブ エンドポイントを選択します。アプリケーションのすべての依存関係をチェックする正常性エンドポイントを構築することを検討してください。", "waf": "確実" }, { "category": "ネットワークトポロジと接続性", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "A01.18", + "id": "A01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "低い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door で HEAD 正常性プローブを使用して、Front Door がアプリケーションに送信するトラフィックを減らします。", "waf": "パフォーマンス" }, @@ -209,10 +233,10 @@ "category": "ネットワークトポロジと接続性", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "A01.19", + "id": "A01.21", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリ配信 - Load Balancer", "text": "Load Balancer の送信規則の代わりに Azure NAT Gateway を使用して、SNAT のスケーラビリティを向上させる", "waf": "確実" }, @@ -220,20 +244,20 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "A01.20", + "id": "A01.22", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door でマネージド TLS 証明書を使用します。運用コストと、証明書の更新による停止のリスクを軽減します。", "waf": "オペレーションズ" }, { "category": "ネットワークトポロジと接続性", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "A01.21", + "id": "A01.23", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF の構成をコードとして定義します。コードを使用することで、新しいルールセット・バージョンをより簡単に採用し、保護を強化できます。", "waf": "オペレーションズ" }, @@ -241,20 +265,20 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "A02.01", + "id": "A01.24", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door でエンド ツー エンドの TLS を使用します。クライアントから Front Door への接続、および Front Door から配信元への接続には TLS を使用します。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "A02.02", + "id": "A01.25", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door で HTTP から HTTPS へのリダイレクトを使用します。古いクライアントをHTTPSリクエストに自動的にリダイレクトすることでサポートします。", "waf": "安全" }, @@ -262,10 +286,10 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "A02.03", + "id": "A01.26", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF を有効にします。さまざまな攻撃からアプリケーションを保護します。", "waf": "安全" }, @@ -273,10 +297,10 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "A02.04", + "id": "A01.27", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "ワークロードに合わせて Azure Front Door WAF を調整します。誤検知を減らします。", "waf": "安全" }, @@ -284,10 +308,10 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "A02.05", + "id": "A01.28", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF で防止モードを使用します。防止モードにより、WAF は悪意のある要求を確実にブロックします。", "waf": "安全" }, @@ -295,10 +319,10 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "A02.06", + "id": "A01.29", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF の既定のルール セットを有効にします。既定のルール セットは、一般的な攻撃を検出してブロックします。", "waf": "安全" }, @@ -306,60 +330,60 @@ "ammp": true, "category": "ネットワークトポロジと接続性", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "A02.07", + "id": "A01.30", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "高い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF ボット管理ルールを有効にします。ボットルールは、良いボットと悪いボットを検出します。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "A02.08", + "id": "A01.31", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "最新バージョンの Azure Front Door WAF ルールセットを使用します。ルールセットの更新は、現在の脅威の状況を考慮して定期的に更新されます。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "A02.09", + "id": "A01.32", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF にレート制限を追加します。レート制限は、クライアントが短期間に大量のトラフィックを誤ってまたは意図的に送信することをブロックします。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "A02.10", + "id": "A01.33", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF のレート制限には、高いしきい値を使用します。高いレート制限しきい値は、正当なトラフィックのブロックを回避しながら、インフラストラクチャを圧倒する可能性のある非常に多数の要求に対する保護を提供します。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "A02.11", + "id": "A01.34", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "低い", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF を使用してトラフィックを geo フィルター処理します。想定されるリージョンからのトラフィックのみを許可し、他のリージョンからのトラフィックをブロックします。", "waf": "安全" }, { "category": "ネットワークトポロジと接続性", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "A02.12", + "id": "A01.35", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "中程度", - "subcategory": "アプリ配信", + "subcategory": "アプリの配信 - Front Door", "text": "Azure Front Door WAF を使用してトラフィックをジオフィルター処理するときに、不明な (ZZ) 場所を指定します。IP アドレスを地理的に一致させることができない場合に、正当な要求を誤ってブロックしないようにします。", "waf": "安全" } @@ -367,7 +391,7 @@ "metadata": { "name": "Azure Application Delivery Networking", "state": "GA", - "timestamp": "November 07, 2023" + "timestamp": "November 21, 2023" }, "severities": [ { diff --git a/checklists/network_appdelivery_checklist.ko.json b/checklists/network_appdelivery_checklist.ko.json index 57c4689a2..85504cd8c 100644 --- a/checklists/network_appdelivery_checklist.ko.json +++ b/checklists/network_appdelivery_checklist.ko.json @@ -11,7 +11,7 @@ "id": "A01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door에서 고객 관리형 TLS 인증서를 사용하는 경우 '최신' 인증서 버전을 사용합니다. 수동 인증서 갱신으로 인한 중단 위험을 줄입니다.", "waf": "작업" }, @@ -33,7 +33,7 @@ "id": "A01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - App Gateway", "text": "Application Gateway v2 SKU를 사용하고 있는지 확인합니다.", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "안전" @@ -45,19 +45,19 @@ "id": "A01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 제공 - Load Balancer", "text": "Azure Load Balancer에 표준 SKU를 사용하고 있는지 확인합니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", - "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", "id": "A01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "보통", - "subcategory": "앱 제공", - "text": "응용 프로그램 게이트웨이는 IP 접두사가 /26보다 크거나 같은 서브넷에 배포해야 합니다", + "subcategory": "앱 배달 - App Gateway", + "text": "Application Gateway v2는 IP 접두사가 /24보다 크거나 같은 서브넷에 배포해야 합니다.", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "안전" }, @@ -68,7 +68,7 @@ "id": "A01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - App Gateway", "text": "랜딩 영역 가상 네트워크 내에서 그리고 보안 중인 앱을 사용하여 인바운드 HTTP(S) 연결을 프록시하는 데 사용되는 Azure Application Gateway v2 또는 파트너 NVA를 배포합니다.", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "안전" @@ -79,18 +79,42 @@ "id": "A01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - App Gateway", "text": "애플리케이션 랜딩 존의 모든 공용 IP 주소에 대해 DDoS 네트워크 또는 IP 보호 계획을 사용합니다.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", "id": "A01.08", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "severity": "보통", + "subcategory": "앱 배달 - App Gateway", + "text": "최소 인스턴스 수를 2개로 자동 크기 조정을 구성합니다.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "신뢰도" + }, + { + "category": "네트워크 토폴로지 및 연결", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", + "id": "A01.09", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", + "severity": "보통", + "subcategory": "앱 배달 - App Gateway", + "text": "가용성 영역에 Application Gateway 배포", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "신뢰도" + }, + { + "category": "네트워크 토폴로지 및 연결", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "WAF 정책과 함께 Azure Front Door를 사용하여 여러 Azure 지역에 걸쳐 있는 글로벌 HTTP/S 앱을 제공하고 보호할 수 있습니다.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "안전" @@ -98,7 +122,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", - "id": "A01.09", + "id": "A01.11", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "보통", "subcategory": "앱 제공", @@ -110,10 +134,10 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "A01.10", + "id": "A01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Traffic Manager", "text": "Traffic Manager를 사용하여 HTTP/S 이외의 프로토콜에 걸쳐 있는 글로벌 앱을 제공합니다.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "신뢰도" @@ -121,7 +145,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "A01.11", + "id": "A01.13", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "낮다", "subcategory": "앱 제공", @@ -132,7 +156,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "A01.12", + "id": "A01.14", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "보통", "subcategory": "앱 제공", @@ -145,10 +169,10 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "A01.13", + "id": "A01.15", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "'방지' 모드에서 Front Door에 대한 WAF 프로필을 배포합니다.", "waf": "안전" }, @@ -156,10 +180,10 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "A01.14", + "id": "A01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Traffic Manager와 Azure Front Door를 결합하지 마세요.", "waf": "안전" }, @@ -167,40 +191,40 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "A01.15", + "id": "A01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door 및 원본에서 동일한 도메인 이름을 사용합니다. 호스트 이름이 일치하지 않으면 미묘한 버그가 발생할 수 있습니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "A01.16", + "id": "A01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "낮다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door 원본 그룹에 원본이 하나만 있는 경우 상태 프로브를 사용하지 않도록 설정합니다.", "waf": "공연" }, { "category": "네트워크 토폴로지 및 연결", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "A01.17", + "id": "A01.19", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door에 대한 양호한 상태 프로브 엔드포인트를 선택합니다. 애플리케이션의 모든 종속성을 확인하는 상태 엔드포인트를 빌드하는 것이 좋습니다.", "waf": "신뢰도" }, { "category": "네트워크 토폴로지 및 연결", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "A01.18", + "id": "A01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "낮다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door와 함께 HEAD 상태 프로브를 사용하여 Front Door가 애플리케이션으로 보내는 트래픽을 줄입니다.", "waf": "공연" }, @@ -209,10 +233,10 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "A01.19", + "id": "A01.21", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 제공 - Load Balancer", "text": "SNAT 확장성 향상을 위해 Load Balancer 아웃바운드 규칙 대신 Azure NAT Gateway 사용", "waf": "신뢰도" }, @@ -220,20 +244,20 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "A01.20", + "id": "A01.22", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door에서 관리형 TLS 인증서를 사용합니다. 운영 비용을 줄이고 인증서 갱신으로 인한 중단 위험을 줄입니다.", "waf": "작업" }, { "category": "네트워크 토폴로지 및 연결", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "A01.21", + "id": "A01.23", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF 구성을 코드로 정의합니다. 코드를 사용하면 새 규칙 집합 버전을 보다 쉽게 채택하고 추가 보호를 얻을 수 있습니다.", "waf": "작업" }, @@ -241,20 +265,20 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "A02.01", + "id": "A01.24", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door에서 엔드투엔드 TLS를 사용합니다. 클라이언트에서 Front Door로, Front Door에서 원본으로 연결하는 데 TLS를 사용합니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "A02.02", + "id": "A01.25", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door에서 HTTP에서 HTTPS로 리디렉션을 사용합니다. 이전 클라이언트를 HTTPS 요청으로 자동 리디렉션하여 지원합니다.", "waf": "안전" }, @@ -262,10 +286,10 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "A02.03", + "id": "A01.26", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF를 사용하도록 설정합니다. 다양한 공격으로부터 애플리케이션을 보호합니다.", "waf": "안전" }, @@ -273,10 +297,10 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "A02.04", + "id": "A01.27", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "워크로드에 맞게 Azure Front Door WAF를 튜닝합니다. 가양성 탐지를 줄입니다.", "waf": "안전" }, @@ -284,10 +308,10 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "A02.05", + "id": "A01.28", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF에서 방지 모드를 사용합니다. 방지 모드는 WAF가 악의적인 요청을 차단하도록 합니다.", "waf": "안전" }, @@ -295,10 +319,10 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "A02.06", + "id": "A01.29", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF 기본 규칙 집합을 사용하도록 설정합니다. 기본 규칙 집합은 일반적인 공격을 탐지하고 차단합니다.", "waf": "안전" }, @@ -306,60 +330,60 @@ "ammp": true, "category": "네트워크 토폴로지 및 연결", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "A02.07", + "id": "A01.30", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "높다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF 봇 관리 규칙을 사용하도록 설정합니다. 봇 규칙은 좋은 봇과 나쁜 봇을 감지합니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "A02.08", + "id": "A01.31", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "최신 Azure Front Door WAF 규칙 집합 버전을 사용합니다. 규칙 집합 업데이트는 현재 위협 환경을 고려하기 위해 정기적으로 업데이트됩니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "A02.09", + "id": "A01.32", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF에 속도 제한을 추가합니다. 속도 제한은 클라이언트가 실수로 또는 의도적으로 짧은 시간에 많은 양의 트래픽을 보내는 것을 차단합니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "A02.10", + "id": "A01.33", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF 속도 제한에 높은 임계값을 사용합니다. 높은 속도 제한 임계값은 합법적인 트래픽 차단을 방지하는 동시에 인프라를 압도할 수 있는 매우 많은 수의 요청에 대한 보호 기능을 제공합니다. ", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "A02.11", + "id": "A01.34", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "낮다", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF를 사용하여 트래픽을 지역 필터링합니다. 예상 지역의 트래픽만 허용하고 다른 지역의 트래픽은 차단합니다.", "waf": "안전" }, { "category": "네트워크 토폴로지 및 연결", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "A02.12", + "id": "A01.35", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "보통", - "subcategory": "앱 제공", + "subcategory": "앱 배달 - Front Door", "text": "Azure Front Door WAF를 사용하여 트래픽을 지리적으로 필터링할 때 알 수 없는(ZZ) 위치를 지정합니다. IP 주소를 지리적으로 일치시킬 수 없는 경우 합법적인 요청을 실수로 차단하지 않도록 합니다.", "waf": "안전" } @@ -367,7 +391,7 @@ "metadata": { "name": "Azure Application Delivery Networking", "state": "GA", - "timestamp": "November 07, 2023" + "timestamp": "November 21, 2023" }, "severities": [ { diff --git a/checklists/network_appdelivery_checklist.pt.json b/checklists/network_appdelivery_checklist.pt.json index 403915226..efdb107ff 100644 --- a/checklists/network_appdelivery_checklist.pt.json +++ b/checklists/network_appdelivery_checklist.pt.json @@ -11,7 +11,7 @@ "id": "A01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Se você usar certificados TLS gerenciados pelo cliente com o Azure Front Door, use a versão de certificado 'Mais recente'. Reduza o risco de paralisações causadas pela renovação manual de certificados.", "waf": "Operações" }, @@ -33,7 +33,7 @@ "id": "A01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - App Gateway", "text": "Verifique se você está usando o SKU do Application Gateway v2", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Segurança" @@ -45,19 +45,19 @@ "id": "A01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Load Balancer", "text": "Verifique se você está usando a SKU padrão para seus Balanceadores de Carga do Azure", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", - "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", "id": "A01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "Média", - "subcategory": "Entrega de aplicativos", - "text": "Seus gateways de aplicativo devem ser implantados em sub-redes com prefixos IP iguais ou maiores que /26", + "subcategory": "Entrega de aplicativos - App Gateway", + "text": "Seus Application Gateways v2 devem ser implantados em sub-redes com prefixos IP iguais ou maiores que /24", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Segurança" }, @@ -68,7 +68,7 @@ "id": "A01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - App Gateway", "text": "Implante o Gateway de Aplicativo do Azure v2 ou NVAs de parceiros usados para fazer proxy de conexões HTTP(S) de entrada na rede virtual da zona de aterrissagem e com os aplicativos que eles estão protegendo.", "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Segurança" @@ -79,18 +79,42 @@ "id": "A01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - App Gateway", "text": "Use uma rede DDoS ou planos de proteção IP para todos os endereços IP públicos nas zonas de aterrissagem do aplicativo.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", "id": "A01.08", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "severity": "Média", + "subcategory": "Entrega de aplicativos - App Gateway", + "text": "Configure o dimensionamento automático com uma quantidade mínima de duas instâncias.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Fiabilidade" + }, + { + "category": "Topologia de rede e conectividade", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", + "id": "A01.09", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", + "severity": "Média", + "subcategory": "Entrega de aplicativos - App Gateway", + "text": "Implantar o Application Gateway em zonas de disponibilidade", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Fiabilidade" + }, + { + "category": "Topologia de rede e conectividade", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use o Azure Front Door com políticas WAF para fornecer e ajudar a proteger aplicativos HTTP/S globais que abrangem várias regiões do Azure.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Segurança" @@ -98,7 +122,7 @@ { "category": "Topologia de rede e conectividade", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", - "id": "A01.09", + "id": "A01.11", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -110,10 +134,10 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "A01.10", + "id": "A01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Gerenciador de Tráfego", "text": "Use o Gerenciador de Tráfego para fornecer aplicativos globais que abrangem protocolos diferentes de HTTP/S.", "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", "waf": "Fiabilidade" @@ -121,7 +145,7 @@ { "category": "Topologia de rede e conectividade", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "A01.11", + "id": "A01.13", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Baixo", "subcategory": "Entrega de aplicativos", @@ -132,7 +156,7 @@ { "category": "Topologia de rede e conectividade", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "A01.12", + "id": "A01.14", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -145,10 +169,10 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "A01.13", + "id": "A01.15", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Implante seus perfis WAF para Front Door no modo 'Prevenção'.", "waf": "Segurança" }, @@ -156,10 +180,10 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "A01.14", + "id": "A01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Evite combinar o Gerenciador de Tráfego do Azure e o Azure Front Door.", "waf": "Segurança" }, @@ -167,40 +191,40 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "A01.15", + "id": "A01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use o mesmo nome de domínio no Azure Front Door e sua origem. Nomes de host incompatíveis podem causar bugs sutis.", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "A01.16", + "id": "A01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "Baixo", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Desabilite os testes de integridade quando houver apenas uma origem em um grupo de origem do Azure Front Door.", "waf": "Desempenho" }, { "category": "Topologia de rede e conectividade", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "A01.17", + "id": "A01.19", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Selecione bons pontos de extremidade de teste de integridade para o Azure Front Door. Considere a criação de pontos de extremidade de integridade que verifiquem todas as dependências do seu aplicativo.", "waf": "Fiabilidade" }, { "category": "Topologia de rede e conectividade", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "A01.18", + "id": "A01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "Baixo", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use testes de integridade do HEAD com o Azure Front Door para reduzir o tráfego que o Front Door envia para seu aplicativo.", "waf": "Desempenho" }, @@ -209,10 +233,10 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "A01.19", + "id": "A01.21", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Load Balancer", "text": "Usar o Gateway NAT do Azure em vez das regras de saída do Load Balancer para melhor escalabilidade do SNAT", "waf": "Fiabilidade" }, @@ -220,20 +244,20 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "A01.20", + "id": "A01.22", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use certificados TLS gerenciados com o Azure Front Door. Reduza o custo operacional e o risco de paralisações devido a renovações de certificados.", "waf": "Operações" }, { "category": "Topologia de rede e conectividade", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "A01.21", + "id": "A01.23", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Defina sua configuração do WAF do Azure Front Door como código. Usando o código, você pode adotar mais facilmente novas versões do conjunto de regras e obter proteção adicional.", "waf": "Operações" }, @@ -241,20 +265,20 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "A02.01", + "id": "A01.24", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use o TLS de ponta a ponta com o Azure Front Door. Use o TLS para conexões de seus clientes com o Front Door e do Front Door com sua origem.", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "A02.02", + "id": "A01.25", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use o redirecionamento HTTP para HTTPS com o Azure Front Door. Ofereça suporte a clientes mais antigos redirecionando-os para uma solicitação HTTPS automaticamente.", "waf": "Segurança" }, @@ -262,10 +286,10 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "A02.03", + "id": "A01.26", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Habilite o WAF do Azure Front Door. Proteja seu aplicativo contra uma série de ataques.", "waf": "Segurança" }, @@ -273,10 +297,10 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "A02.04", + "id": "A01.27", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Ajuste o WAF do Azure Front Door para sua carga de trabalho. Reduza as detecções de falsos positivos.", "waf": "Segurança" }, @@ -284,10 +308,10 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "A02.05", + "id": "A01.28", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use o modo de prevenção com o WAF do Azure Front Door. O modo de prevenção garante que o WAF bloqueie solicitações maliciosas.", "waf": "Segurança" }, @@ -295,10 +319,10 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "A02.06", + "id": "A01.29", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Habilite os conjuntos de regras padrão do WAF do Azure Front Door. Os conjuntos de regras padrão detectam e bloqueiam ataques comuns.", "waf": "Segurança" }, @@ -306,60 +330,60 @@ "ammp": true, "category": "Topologia de rede e conectividade", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "A02.07", + "id": "A01.30", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "Alto", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Habilite as regras de gerenciamento de bot do WAF do Azure Front Door. As regras de bot detectam bots bons e ruins.", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "A02.08", + "id": "A01.31", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use as versões mais recentes do conjunto de regras do WAF do Azure Front Door. As atualizações do conjunto de regras são atualizadas regularmente para levar em conta o cenário atual de ameaças.", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "A02.09", + "id": "A01.32", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Adicione o limite de taxa ao WAF do Azure Front Door. A limitação de taxa bloqueia clientes que enviam acidentalmente ou intencionalmente grandes quantidades de tráfego em um curto período de tempo.", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "A02.10", + "id": "A01.33", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Use um limite alto para os limites de taxa do WAF do Azure Front Door. Limites de limite de taxa alta evitam o bloqueio de tráfego legítimo, ao mesmo tempo em que fornecem proteção contra um número extremamente alto de solicitações que podem sobrecarregar sua infraestrutura. ", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "A02.11", + "id": "A01.34", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "Baixo", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Filtre geograficamente o tráfego usando o WAF do Azure Front Door. Permita o tráfego apenas de regiões esperadas e bloqueie o tráfego de outras regiões.", "waf": "Segurança" }, { "category": "Topologia de rede e conectividade", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "A02.12", + "id": "A01.35", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "Média", - "subcategory": "Entrega de aplicativos", + "subcategory": "Entrega de aplicativos - Front Door", "text": "Especifique o local desconhecido (ZZ) ao filtrar geograficamente o tráfego com o WAF do Azure Front Door. Evite bloquear acidentalmente solicitações legítimas quando os endereços IP não puderem ser correspondidos geograficamente.", "waf": "Segurança" } @@ -367,7 +391,7 @@ "metadata": { "name": "Azure Application Delivery Networking", "state": "GA", - "timestamp": "November 07, 2023" + "timestamp": "November 21, 2023" }, "severities": [ { diff --git a/checklists/network_appdelivery_checklist.zh-Hant.json b/checklists/network_appdelivery_checklist.zh-Hant.json new file mode 100644 index 000000000..d84061370 --- /dev/null +++ b/checklists/network_appdelivery_checklist.zh-Hant.json @@ -0,0 +1,454 @@ +{ + "categories": [ + { + "name": "網路拓撲和連接" + } + ], + "items": [ + { + "category": "網路拓撲和連接", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "如果將客戶管理的 TLS 證書用於 Azure Front Door,請使用“最新”證書版本。降低手動證書續訂導致的中斷風險。", + "waf": "操作" + }, + { + "category": "網路拓撲和連接", + "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", + "severity": "中等", + "subcategory": "應用交付", + "text": "在登陸區域內為面向內部 (公司) 和面向外部的應用 (連線) 執行應用交付。", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", + "guid": "553585a6-abe0-11ed-afa1-0242ac120002", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "severity": "中等", + "subcategory": "應用交付 - 應用閘道", + "text": "確保使用應用程式閘道 v2 SKU", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "A01.04", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "severity": "中等", + "subcategory": "應用交付 - 負載均衡器", + "text": "確保將標準 SKU 用於 Azure 負載均衡器", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant", + "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "A01.05", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", + "severity": "中等", + "subcategory": "應用交付 - 應用閘道", + "text": "應用程式閘道 v2 應部署在IP前綴等於或大於 /24 的子網中", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "description": "一般而言,反向代理(尤其是 WAF)的管理更接近應用程式而不是網路,因此它們與應用程式屬於同一訂閱。如果應用程式閘道和 WAF 由一個團隊管理,則可以將應用程式閘道和 WAF 集中到連接訂閱中。", + "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "A01.06", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "severity": "中等", + "subcategory": "應用交付 - 應用閘道", + "text": "部署 Azure 應用程式閘道 v2 或合作夥伴 NVA,用於在登陸區域虛擬網路中代理入站 HTTP(S) 連接,並使用它們保護的應用。", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "A01.07", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "severity": "中等", + "subcategory": "應用交付 - 應用閘道", + "text": "對應用程式登陸區域中的所有公共IP位址使用 DDoS 網路或IP保護計畫。", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "135bf4ac-f9db-461f-b76b-2ee9e30b12c0", + "id": "A01.08", + "link": "https://learn.microsoft.com/azure/application-gateway/application-gateway-autoscaling-zone-redundant", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(properties.autoscaleConfiguration) and properties.autoscaleConfiguration.minCapacity >= 2) | distinct id,compliant", + "severity": "中等", + "subcategory": "應用交付 - 應用閘道", + "text": "配置自動縮放,最小實例數為 2。", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "可靠性" + }, + { + "category": "網路拓撲和連接", + "guid": "060c6964-52b5-48db-af8b-83e4b2d85349", + "id": "A01.09", + "link": "https://learn.microsoft.com/azure/reliability/migrate-app-gateway-v2", + "query": "resources | where type =~ 'microsoft.network/applicationGateways' | extend compliant = (isnotnull(zones) and array_length(zones) > 1) | distinct id,compliant", + "severity": "中等", + "subcategory": "應用交付 - 應用閘道", + "text": "跨可用性區域部署應用程式閘道", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "可靠性" + }, + { + "category": "網路拓撲和連接", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "A01.10", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "將 Azure Front Door 與 WAF 策略結合使用,以交付和幫助保護跨多個 Azure 區域的全球 HTTP/S 應用。", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "A01.11", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "severity": "中等", + "subcategory": "應用交付", + "text": "使用 Front Door 和應用程式閘道幫助保護 HTTP/S 應用時,請在 Front Door 中使用 WAF 策略。鎖定應用程式閘道以僅接收來自 Front Door 的流量。", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "A01.12", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "severity": "高", + "subcategory": "應用交付 - 流量管理員", + "text": "使用流量管理器交付跨 HTTP/S 以外的協定的全域應用。", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "可靠性" + }, + { + "category": "網路拓撲和連接", + "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "A01.13", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "severity": "低", + "subcategory": "應用交付", + "text": "如果使用者只需要存取內部應用程式,是否將 Microsoft Entra ID 應用程式代理視為 Azure 虛擬桌面 (AVD) 的替代方案?", + "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "A01.14", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "severity": "中等", + "subcategory": "應用交付", + "text": "若要減少為網路中的傳入連接打開的防火牆埠數,請考慮使用 Microsoft Entra ID 應用程式代理為遠端使用者提供對內部應用程式的安全且經過身份驗證的訪問。", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", + "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "A01.15", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "在「預防」模式下部署 Front Door 的 WAF 配置檔。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "A01.16", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "避免結合使用 Azure 流量管理器和 Azure Front Door。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "A01.17", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "在 Azure Front Door 和源上使用相同的功能變數名稱。不匹配的主機名可能會導致細微的錯誤。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "A01.18", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", + "severity": "低", + "subcategory": "應用交付 - Front Door", + "text": "當 Azure Front Door 源組中只有一個源時,禁用運行狀況探測。", + "waf": "性能" + }, + { + "category": "網路拓撲和連接", + "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "A01.19", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "為 Azure Front Door 選擇運行狀況良好的探測終結點。請考慮生成用於檢查應用程式的所有依賴項的運行狀況終結點。", + "waf": "可靠性" + }, + { + "category": "網路拓撲和連接", + "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "A01.20", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", + "severity": "低", + "subcategory": "應用交付 - Front Door", + "text": "將 HEAD 運行狀況探測與 Azure Front Door 配合使用,以減少 Front Door 發送到應用程式的流量。", + "waf": "性能" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", + "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "A01.21", + "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", + "severity": "高", + "subcategory": "應用交付 - 負載均衡器", + "text": "使用 Azure NAT 閘道而不是負載均衡器出站規則,以獲得更好的 SNAT 可伸縮性", + "waf": "可靠性" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "A01.22", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "將託管 TLS 證書與 Azure Front Door 配合使用。降低運營成本和因證書續訂而導致的中斷風險。", + "waf": "操作" + }, + { + "category": "網路拓撲和連接", + "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "A01.23", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "將 Azure Front Door WAF 配置定義為代碼。通過使用代碼,您可以更輕鬆地採用新的規則集版本並獲得額外的保護。", + "waf": "操作" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "A01.24", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "將端到端 TLS 與 Azure Front Door 配合使用。將 TLS 用於從用戶端到 Front Door 的連接,以及從 Front Door 到源的連接。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "A01.25", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "將 HTTP 到 HTTPS 重定向與 Azure Front Door 配合使用。通過自動將舊用戶端重定向到 HTTPS 請求來支持它們。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "A01.26", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "啟用 Azure Front Door WAF。保護您的應用程式免受一系列攻擊。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "A01.27", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "針對工作負載優化 Azure Front Door WAF。減少誤報檢測。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "A01.28", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "將預防模式與 Azure Front Door WAF 配合使用。防護模式可確保WAF攔截惡意請求。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "A01.29", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "啟用 Azure Front Door WAF 預設規則集。默認規則集檢測並阻止常見攻擊。", + "waf": "安全" + }, + { + "ammp": true, + "category": "網路拓撲和連接", + "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "A01.30", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", + "severity": "高", + "subcategory": "應用交付 - Front Door", + "text": "啟用 Azure Front Door WAF 機器人管理規則。機器人規則可檢測好的和壞的機器人。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "A01.31", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "使用最新的 Azure Front Door WAF 規則集版本。規則集更新會定期更新,以考慮當前的威脅形勢。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "A01.32", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "向 Azure Front Door WAF 添加速率限制。速率限制會阻止客戶端在短時間內意外或有意發送大量流量。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "A01.33", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "對 Azure Front Door WAF 速率限制使用高閾值。高速率限制閾值可避免阻止合法流量,同時仍可防止可能使基礎架構不堪重負的大量請求。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "A01.34", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", + "severity": "低", + "subcategory": "應用交付 - Front Door", + "text": "使用 Azure Front Door WAF 對流量進行異地篩選。僅允許來自預期區域的流量,並阻止來自其他區域的流量。", + "waf": "安全" + }, + { + "category": "網路拓撲和連接", + "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "A01.35", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", + "severity": "中等", + "subcategory": "應用交付 - Front Door", + "text": "使用 Azure Front Door WAF 對流量進行異地篩選時,指定未知 (ZZ) 位置。避免在IP位址無法進行地理匹配時意外阻止合法請求。", + "waf": "安全" + } + ], + "metadata": { + "name": "Azure Application Delivery Networking", + "state": "GA", + "timestamp": "November 21, 2023" + }, + "severities": [ + { + "name": "高" + }, + { + "name": "中等" + }, + { + "name": "低" + } + ], + "status": [ + { + "description": "此檢查尚未查看", + "name": "未驗證" + }, + { + "description": "有一個與此檢查關聯的操作項", + "name": "打開" + }, + { + "description": "此檢查已經過驗證,沒有與之關聯的其他操作項", + "name": "實現" + }, + { + "description": "建議已理解,但當前要求不需要", + "name": "不需要" + }, + { + "description": "不適用於當前設計", + "name": "不適用" + } + ], + "waf": [ + { + "name": "可靠性" + }, + { + "name": "安全" + }, + { + "name": "成本" + }, + { + "name": "操作" + }, + { + "name": "性能" + } + ], + "yesno": [ + { + "name": "是的" + }, + { + "name": "不" + } + ] +} \ No newline at end of file diff --git a/spreadsheet/macrofree/checklist.en.master.xlsx b/spreadsheet/macrofree/checklist.en.master.xlsx index e2c2f14208c0cf10ae826fb642719e545f2f2284..064dc4ef5503a896858cfb8ebe87faf3c546f10d 100644 GIT binary patch literal 285547 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

T(C(P0LRl5J}3=>amFZu$sD+Bn(L@LY80XY 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

AA-kn^@4saY5NI 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�S4p2kvmhh6tNn=fT&Y^b0VZQpbC#9Tbb- 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
wEA zw949>8GGdQ(syS;IGI{yVa<%-*LJWnFCmO^I>hh-D7w;hcC)=(I(vK-j-EV`e{e8Z3gDVkM2L1jJ7Ks%OH_!qj1$B1r ze!R8ty^#DwrN0u=VMJWM5>)@~!*Au0c6I%A%ulcM9RN>Cm(eeyPmw$&4R(wzqi0I*$>0Tc6M8=>|c)r~6I$d;Frlf9K*?0+plz z(xJWFmWX@YW<51Iw%mtF&u@XoRI6E2RN{2aA7b52MOIHe~Jp&*%T$AX#2aR3tOV+f?2tr-$|2@r-gb_1Xni;iSM5}PuZ5YBG}S(Sy$)$i9*YEJedyaV2zZf%C<#T31y z`YA<6@T7c8gkuS;Cw~GwcOI^E#_&m^e)Qu+hNiZA8oeiJgz1q!3j&zxzAeDt*LZ~D zZ((KsSP4l56|e1FFMsd3_h=QeYhxUMOj<@Z%?}r?`k>7Gf@}N7^OMsBBti@u=l zdB(0y+Z|<#eoXbo7vOmYmQ5RT)D0*45pz}~ZmdjF;}_|h0!mzOxcF0;koopi)PL5u z)MMV^xMjg1ZGcSLW{fC!e((UIAs|Xr?%sn|I@Oh(N1OW?clYa)z7eBe%HyJ)kSXYc zFJ7%GN?quq!1sfQVhe?QjolxB(;ULA4Z9oj)uOZIRB=6WV-aVTV6PFkF`E?X{H!dj zTD#Nl@GpE(oi{IV9sYWG;IAP;`rd+~3GnYVUIZSJHtHCGyON>ZWd2!BU*I@yYKh0C zXdC1AfW?+pDAAX)CsvPf`0p#-56@c6?e8ql1_80W1M$Yp*JXuIX`?P3;8NP49(h(P zk{5_ind7L+y?$4WsQu~2)$H;*-8oBfcnXZyTITKsr51qaAv^}w%ztWxU`)~h^s(;% zm+`|xX57d^FfT+P!7krkNQTyEh)*^Dl6-xad_Kowz6vG#f)D9IlYf;X!o6^&u8Ho~ zeC2hU+-T{MJ5=iP-c6mEbv%s*s8%GG*-ET@7F z(P6+`y{ep*`|q4rMndw7h7)qZe7FqFRPVVeX6`pFiYR-UJ%IZmZ_<~mPQ%=1W6&y| zxxh~$r^tI-=zdFsf|@{!to`YtQ|LuUwB|pZ3)}!W0FCB~>XV_D$edo*Lm!s8$t>t1 zEFTc~*{7i|wkdq@Gff9?)Bh_#M@L>v$k)e{>eV*pwrc!^TwiS)%0DHwaTUP zfbe|sVXSG`XWA_00ipzcKWrfNKvROhBNQ-#kK0@FJfy;#k-s{Y86svF*o){j1;zTo z6BI`D5#uauJnIJ?hQIl*X|*n=qVSg{2&fAA+asPoDwu=nlU(&J@qw(4>2 z2T8B|+RKk1$Sqdtc7&5R@%TgeI`0kPV3gx`!{(QSxO<@=j^B`sO6td7u*ip{$EbV@ z;E=^_`C)XV_%~?C-Av2ub8RO7e#!NLkTAff@}v22(!Y9n&C7VLYYCFI zkyM^aV%s8y`xqIc!CV0LHhX%TFZDM%dVkAQO=6b4_L4Vx{NQ-}%Xd#w@Vj7E7{Szt zfgysGnUSMSYw2+jVslRU$?fJC1@EKEqy`PR!B9r#VWtrapiG|?IbC~GH$0H zvmO`_W$$Bonw^cw0-yvSt;i}-d?Ir{awf@Ppt3(?H+`8*I6vPM+r!;B>eIFp6`CpQ zk-Rx6_|VN=GkQAH$1z!6y;SS=xz5*8w;(^33jQp`1a^9(!`<+$FR|W#-y<3Z0i?xG^7kCcT zaEF7lA1eH(zAgC&j1Kul+U=rwZn`Apf$c%@69E;ih^TpD9=hl>xTLD6Q2Um*%GbN3 zEmztRKN7L7-oxm%n%-scHvXiL`mI&$e+%7uH)#Cw`8P?hc#CyyVn;U5!%NyU=&>3L zYt8~c0NNFnl3V*j4ZiH=^R3*}e18!+zpiS=j!)wmrHF3C=_n^qH3QS9ksIMeaFQwG zs@>cdBW?!V?p(yS;DGfkx#QPzJx-?cgN!r5U!Pw$PYsTM2-{QP!UxoO zv8r=D)^OT1-+|j-a51`W3p}N5c&98HX_I(+a_iSNAG4Qa5_HpxiNO1k%<0v-odxI{ zo7~Mawp?b02`2>;kK|JJ0h(|ER)z@#g&pCk{)R(})OyY*kI*Sy8T>jOtV|R28$IcD zqjv!?*?&c6Hi*F=+bd9jjp3F<8sF}@M^S$gkmTlGHs<-6@y4{3TR7S0;eiz59R1c% z2N6vX=VL7nf5&sxG4R3Wxq~cUv-iNa-$G2O$WzWg13YQVeYm* zk;}{}Hru8)I4dz~z>8h9HPrS{cg}sa`(nPxx=t|^?K+cO7q$mW6Pp&CHLDgVcIgj^ zCYNf|v`8)dI-U#!Y1K3>%ha-T0@m6I))Xzv_GZoj@QR|g=J2bQw9Ke9ly_G1h_0?? zh>V2+j5l#K^9`Tbq|;ZLe`oFSOrEL9_A?Vhq*&B+rUFydc-6))fmubx-%{XdFr)!s zr)NrbBuZm*>Ea2H7#d(l3;ZaVh8P&7{dr(nQWoK)hDft$cdB8~pyWW9aLnR#*S482 z75t$wK}tP4lH@%vFyg=rNJs;quKx7?$EJcI zjpwUXtwS|E8_)m8)Kx~snKWyHyK92GWgxh_YjAf9?(P=c-Q696YjB6)?mAd-hdaA_ zck}(C`<$M`Th(P<)%CP@@t*LoYdPvr(=wA;z1 z7-j_&QZ?=#qd5SnClGznXxLIb`3tk(12e@z} zYZ$9-eTxU@+SB2uwaF(II~;I6&!0kXMQHY2VhwqQNhttFS!<86 z-B?fm`63{}>p8d?O$ z5Fn#m6#6iG^Ka}36970*hH8#%PlNd zBw?_!Y_s5VwsMC|_^$#IEf`fb0gEsmK&hIlvbm-K+T7GpKzpPC7Tew0?rvfO{PW)aW@c5?{<_a;52_KIVTcit=J+vG7kUutV-mhJeiN3s#%Ie%xT8QL%6I zs7q~EE@GeS*St^6)596Cj3eQq%Sn?08*6EN0vZdW>SqJKj#DCFGHd6i>X3gOxAQmr z4w?z&QcK14t7O%AV8LS_nvA$%QP88r7gCRrN|5Rqo;En2LYZpk{{4a}2rR{K8I9U> z5u5ri!APCDJAgSrfC}FO#&W8G&Kp@Bo~Jnb+#v3ewhFHKEY=ypQ-*PFsb)T8PZU5wzJ<&D@=L2iaxuMe_ z2Hu&eSZcYE5~|%JIdy|jdCRhCw>WkX5xK^Nj?jsuFSm{n9&gRY5 zBwqB?Vy*eblYwmJ=X?X!=F+`?@0|*ShT7-c%?MBT8t_osbzxuTXHkK9OtPzAL0q?3 zfXt<5(>u^>=6;7S$gtn#Cp0?+U#R6?4dsHW6QF|o1VcD{;&P|C?zTAq)cEPqL*s$; z8P_T!<+$+UVH}1$!%E3}&Z$&srL*+EcR@@3r`dRjKoI011po37_AemT;ZtetpmF%f ziFegS_oEyn{`i%-^o@F!>)Yyfi<0`$Yt2)nT%@YDZT2?maA~JAW2@!ebCj&6>LzL(?CotMw`3#)fo~EdUiO<=_h2{Y%k9(iypO@bv&M2J5nhl<( zS;9AqD#s1LjcUbt^{Mo2>pg5Zj!^Faic=axd`o@vj>5B-sRotc>OTW2OVu+mq38xW zOeNz4!L-7tMS9h=dH4$wb*}m7YF^(Aep?p= z$PFKs?^4N|DLck65Y(+s$nab>mXp`L{P1!vaDX2jVT@qJn9*uvzj9=C{~Yi@8}!&g z@#R>#<|!0i+o}uBI6|H;hC}KgVc!r`8>UXvBgbio=A|~5B~1Klrx34rLhIc}RW-1f z@rV~HQ6-5lnUc2+Dtm<)qz+oN5&s(fpBJ_GrO@A?=lx`3q-V=?F7UA~715Tgk0Dnb>OlZcDMPHMrCEsCL@e_1eJBe= zYWy5GNU*xrw=KY0B|r9-PfG1bqd@hjP$hF4rxOP8h^n7#%Dm#w5T319zp*-m0{DRl z98i`CQ2LwzurUU7zx@_4`XSJa1gyex+O5hWImrNY-+ojhjvP+9&t1J*B(qS$H3A>U z?|&jb%V;qA?k2EE&;`5|ij>Xx6yIZZK_7MQijvgKpqEYl&9{RPre1LrlfD7gW;Rc_ zH@#!hgYb_9q(l-4NW+3YFZqWTI`^fTn6j&XBu*N6Cv zFMp~?kl&&YsJfdDLL4MM{6koR{R$^35gztKTx6TN_?Ncs7Et0d9+bS!$EJArBos?D zAQy8I(+hn&B-J|h+*OU0SEt50>bWQywWJrm#C3}+=voRM>bhFK*LT?@JK(?LTcANTX)4!Q(Fhm!+sE6} zecLgV8nDt0fwXy@>%|7C4LDRdsf4I(D@nepTTdgFfZWYzqsx;h)$9|~t+sBr23y*J zdp1D(iXV&)8N%FK6{vZsdco84!A6SU+_dP0VEFxAlW(FN0v8|HQbpCS^#*Pm+gBh5 zU5;4d;hS2F-GtO!v%A!C*nCE{%~GoZB#1cfD4#>_IM$PA%_1#)ww!k&&&V)~ z%oC&4o1hNNr*G!{RDGSvE6XS99%*O(4K_X9iTWMlBO^_Yc#(|$!^)3t|CJ>}*U7T; zmT1W_wEzN_PfZ$u=$BPAar3NvCo32diHgI&dB#y(UYlVO+MP&!8(PZV@{9ZRrPM^^ zcQOP=5+98X|nDjIXoVDK63NY~4$625?q8jxfx$?zK!(41s2OjwAUj(ygHy>DXT#xk3Ul zbeRc53~m0XniSeOhxL%JqSzbu zuNKqzfafQiYv9-C2sK^suvB?$nm85&yD@?Y{9ZZD`QDU^*}MeD^PSU+W*qL8mRn=* z9u`iN9|}XBYT5>pL`IP%x%VS=k=@M*RxG2*=zk{Y1~_*^Qkrq={*amwmhRIkP4NDv z^U-wVq`IAKPj8 z+Sv0lg6<~ANy(;p+nY9fW~;`t;ameVT`@W=+rh%XJBkApm|m?{X?AXt-%-FF(FoM@ zCUU=H5EULJoj0fzP7ei##=FvJ^W=lt6QV3(yg*WTTL9Y^aQG<-^HF$(pi0eP`!@I; zmhHD*N6zY-KT>~myG8ANWl85v9Wr;a{kH~7F3fVy5T4!>D?oi z$T7fn??AUfY05k;mMmZ8_&(@CDY5YAda?YFS!dE2n3nU!;V;RZ@>sheFjB5pnSV{h zg_J@S}pK9~C<9 z;*AZr!dv~x8jr@mrtJDjz;(%=>Y}}2LnC~?Q_B0{7iwfH(`a3SOTb?Fx@8^GXCGEj zBQ#J~zuYD`Xy5!13=(kc=%bRBrX!FOBi<7I%RA@D=zYaG@e-x7eyP{;O%R-}IXP1+ zr^4QE-K9TP=MrW*#3RoOswzxvxR|{Y~0;vRdF*DSOED^Ha-VL3T>#Qmf)DwA_eh)W*u7NRGa&XSrIOb`#ztHHnJph*@yIJ} zDYPv!Tz+JqL)5ScKxj}4**I{PvV4`deAd0>RCfOJm&*{4c<#Gbz@+U$8wd2(cQ~9^ zJTnVQxepP1N<44zpVdz9UG<0?LG`(m#n&JeA2k(|`e|r0Q*#Mgv+H89cTXsRdK!N>*X*PvF;(kT)wL>PD--m$iJsKTS5US9b4WxU{sv^#HnvY|gI4w``e?r+z*EzL;#(A~G zJ`DTc+#YNNfPA0I9KOK&8${G%T<0uKW*&>cCs3tQC#@jB85*}StKk*Q=b-cUbB|Vp z80{-uA5vKZyI%tGrw1Ihz3Nq}zzt{%8efvjIPpXd3{j=xo8*KSuqUHMEX5*C^txi3nojt_-JSI=eQ zu2RecLWjV7`(XuI^(UeV5EgG&(bj4g<>WyM=^p@snNL$pp@hyJ{?67#i~k_z&Ikg> zUa!fES{F3?G|x};c)(oOSiC!;ge8Ql$4=iDsGR%aRk*<};MGmnnS zH5I--D;Ka}HEnm%2)JA*QpMUfsIW)`zZ0xL`nC-}U$9@>v>ytk^2od~BKvX(LqZ(zk-`j-z<#TvyX>}`W+%1V%4Elv@1o{n{U^8K7NHf$IK*n za^6XK3XPr%MV!%-e$k4lKC$Ft?MZz<8mf2WW*Drt;>+7g`K=U+4z;QU9NxMoHzSfNxtTy*6HQ>>@#S}Uvu9*x}GVrp_dRlrl5G21kNn7fwU1W37fc9=U5 zoCe+JsA^gNshg_@FAaIVx|%KGNla+95G(4|r}YR=@P>2p%JgVgOZZU0VxU8y%HN9- z1M7mXCZh`CnPFv%#23}A@H%j{NUR`3tFH2b+Ela3;W2m#OU_;ABt|}Yx@;(Wdm*r2CByi&o{G)}I4ZLjLN412v-cBQ z!OYiAtGgam)d^vl5M;(Z-<)IWxw4}UwKMLnGE51&4@3uKdClf`dW!?U$-0>|0Fj3e#Hf1EhYylAj?CL*-G{2bGkt{b08MjOf)<&_%Yu^Mk}8WN z=RI6(;3rXo>y)w3xi(pQDkyQkRa-W$@=_2W@b0n~Pynyj=HbSHTrY(|Sf7_qj>T#T z0`04i>K1xEcuFi*P!N4+JlAMMz<>#6Ek`w(s_J9-L?6!-I3a~-l>R3G$^T@nR`KC9 z?5*MOKq}FsP-QvU-y|Jmyce#2$e)-z7A`q2uXszkC{BgtyOJRULP1dkCrReoibW-3 zP!bpWU3(#;1-cfk1HT?Cq!Ya-940w(b~XE*|HLAj7R$U8h($6Xt6eM(G~g>keYv>@ZnB!Xd#I!`j_Y4CX}z$&t@A;aM^VC zTkN=@+?6X`DbpgHk0ygTaf@ zV*@Y4uW~}-gsyMfshR{0M^aZkfE9Cqf@`LA)ADOxLz%Qm?G%gaqALnsuMLG2@!eZZ zNz@DHMP>j!I+H=Uhn;NUVqjZEq1N&T2?tL#9%y4eG7)nntU9W>kf%x{QREbcstxLZc)o1t;JU$2P)s_kpHb_TyhEI9fDS zXAU!W#X)-AeUh<0?OGPeD|#u>&x+?TirN`Le^S=5Tq}h;D=Xxnt4PE}9=(}1#$G>{ zE{>CWz!F>Jtbd=D!Q|qU+SAuvp3Np8hHTaDr1TYQZMxiD-JOM~`LOVswE*+X5gpgf zJ>Hh)3>^!&6nc(>%Q~&#BB9GzR&IDaz(^h;BPXkz5lh$yKP3^JdajnqrH!UMi>o*Z zyc5_w6@S8EjODk{Z_!n-&@w(krxmcAqmiy&u(V8fiKe_=xkRyzhUlo?N|XR^NIx0G zgvWPdi}r6rk>!?^o2~qQrcZCS@FQKdNE7Rx{d?~5&4Ji}an`KeG)cN{p<{it_qXtq z%asjteUGZ32WQm^&xI||-sMY@Un!~vcsmGK4dG@~|TRjh|{@OA=y zLGnJw>@N-&wiZ+Z%2Kt7Hm6@2=B2Z$0Y&{nZ9INu3ndykeF9%e@wE@eSH4L-iz;C$ zt4Pk*Ih02@eSqf2_rv+^4gw0Xcb_$ggHZW34WD_A;svu!rx+FENq>WVIId;k7Y zAm*ili@@DUIyGGhNFu=HT!`%H2V`}K725dh5}Oam3{@zN9851Z#H1}amf?#eHD>YB zoi|aYq{lXaeP=d9|G^PRmdJ?UfaY;=4JsoHP%DcC{y)ksBdrr7aFpre%(i)Cem?@F zm=19+2}9GDi7)JmZ_+l+%q*WZxOhh9&TCZD#S6*9v`S2)A8btLg4tQQIB` zqf-0PO4AzDr?jp7<6PXHu{Xwjl-~9$+_JqP>WfAkH7WCh`VYWhMqnCfYx8u62mhe3#M1?=1*S7+GE%q#JKA^)#mTF zqCd{N>Ce`DYnbulAd9JTJ!UZxNGuJhMAfX!U5N}`R#_~MB5-pWiT6xwbN0dW#T#I zrp+)U_JQ3O`M?2l$1PkgshNJv_ z#0@$PXr0i9mvd3R9A-eKvsH8vz)qdV3;Jl5K^U9)=dEH>As9DV?G2IV^! zHgX3yNEdaam~`W*Xps()ctBK*HO<*-v0fe5MR+S3{E4kday)$vH!Kbw1~~FtF#Qf9iWM zc%MF9c=z9Ia6~*4Kb|dkBpc-mw7?b7LB56a6Q#n-4ga3Kur=;>z+&Hh{2-#!wq^aU zkQ-%=`E-r_^_vr+@fRtw0zLl{MBEwujKUbS@fX_DRTWR z%BUb(z93=sgJ>y63rMX;<;hXw%qW?z)gi^(C5=)?rOX_f&kSj8HjV|^0MPn>X<_{A z%y>2$fD58UrXYRONkae&c9QSOA-p+de4DqEbp3n@#VV0<@QiM4KJ>W|Uhbt=P=wvn z(=T&%1H6AszPn@oiVY4+M^e)9>+{w6s+vw^`Sd7?-yyX#nEJlDM``nG_HrSntCX~E zIM&P6*2R;I**Miz5o8p6F?Le1yvxf)R+|VnP}^%%(lXL*nW`k`Cg{G9nTy=*^A;HEfbfoctKJ zNJh|YP@f~A8*NKA_|^vRhDB+h@$ls%*4@^B_g#X1r3L;{!@i3}mN#OtzkCnXDWLH6 zvFZ|-7OsJG8FtdepcVjwoyazOm8E9$X!NP~6y|UcppEb$9*R@Q+tpB6aEeD`*C{C? zI+J>_xBV#zUEz6In05t}+d@CYPXCFxrKDxNyLl~z#z=a8i-{|Xbr1NM zCGxAmU9z_?pW=(x~@1K8dh3pC#1y5VuWZZ0OtQKmVv^#{;wow z&O%|w($kRq2Filb)`z;#mTYQrnHZEjQXh!!SY)T|FQv?5*)Dc63d`erBizpdT*(53 zX@TJ^MoBa(i`oz?IUiJy(3{t%vnSC6mdadC>QN%1+ZBkxm^47nCkvLilz1S$7#x;X z0_1$aNFZsL(!)d*B*3;wjqL&V*`ipYl`>=WIfoQ_a5eQ)Tz90Pl|TQ##~oIY1J=Pr z5dQc#c|azp;U3mOqXOT<3r5h%C^Tbv)fIt16}4;Jp8m$->n&1V@u{kn_ATH>5H;pX z4Q9{4K$ELy`NPpC>k<0dA;F^J+?hr_yF33k-8~V$R*YYT=>P?jDbqRQyxXGB+d8em z6M5*ZD(S=2W>m`GH$QI?H~W85>RPoBR&Iubvz>5Fed~LIYcqJN4o0o=P>-;URb$rf z?XpMd?%ss!<5ijhUG-P5k4Jhk7MsBJS*Dp!phFvr)hn7_GNBlyo{K@3usz1wvfDU^Xt|_lGmc~9W z!i5&Cp-#{qn|~GjxGylMcrJ^WF|$MlMxd#YP_|?iHkzd=vOn1d&_>say&gh2l#w!z z`Gf^R^<9Y!)YWZ{Se`Y2sc%+&ug*F1jx2#<5-M7H2C#kNU-^2?i8cRP<^$neJM>aU*@<`zt-ozyAhaj{2h3%Q!y$TW z#Q_H{ZKT zs0ZwUIl{IK?V#PX_9h0s?`7FWTI)5PTh3aq-5_{sQKRZm-0lpqXG{#g`Vcckn4!a; z(`mzCs=nTohRE^pW<%wyH_JrO&ceYA6ZE=DW-kT7Pto{juoNfAmO`>zasq>NX!p1V z9$C(aijHIstl^_lO%-?AD=)&Q7)}W7ng1a|jx!!aMEqYwWO9Lskc-oig3TnYUhKU1 z_JefIsR~@)AQ>q(I=VmEvh{=Fp(zt40W!QYX8>3s*oK`(!db?F9UO8xb)pTlL{Arluolu>LRBygS+sDy3 zhT|IsoCZNmL({(E9V%Rx3j!{jXk#?xlqqp!u$3WOa!FexzM^dfgoEKILk8uN%I?Zw zY77F=kL)<7@M4oSu*EAt{nh!=uaF0z75`IJDT@aEv?(_LgjuN+X1RGurTf$6VC=hX zvxJ%83_{W*SxOM3QtwY|aSK-EN6jcOy<6q_$R{WCZ5h{7dOEs^O z8`+TbT@_~UEh_AmZ;jd;$c|um%f2w}EW2BkKXpNY+AUh)b^o^4Bw`NJf%ty#R*Tm&AvnDk1I)kM<}yHvdDg zXS5wzOOxGSAf5LhB>aBfUW71D{w2PF7;j~U1hl(l)T{U1Gi%RP)p+mC8llXn<&j={ zsvTy|PY8kiE{1wkbZBWw&d?k^VhL6&TyY{%)SQ=FJ3e=-^IoWuu4Uh(?z@&e>#tmK zG9oLMPTy2idS{7x!dShFvWL140BboKVcRt53kEes4PO z#13T-_)CDPp}`@D4ql0Mywei->y3rINORFOT9WsdXKaGpImyZ`)% z-9)(WX3(K>OkBweT)H*qJu>gLWR$~7)UnLqT7wox&MyR@c8105{}p4dCyw*7Bt_*m1`wWf>}hO);!u zflbZofV*CE$4LBH@F4-0n@JyCb=Z%S(tqb$Ejgk#*1V8Z)>cyyRPGON0*KY9A69V{ zwjDZ+QFo2h$r65rZ8;L`UR=25e2Uw!IMJlWkp4v)IsvxoXIp1vB1jL|Hme&rmI?+_ zK*~|}!JKtt#H7%l+zqzTMXNG(lQP)9p|os?zX@zwY%gcG_ej;7e2i`>>|Ppzz6k!TYx*l(c zk8Ev7>%(7^OM78+NIf+6H-qDM<*b(urwYuS!A~L84sVHC|eZRc zD~}$ZxD#?FB(o!|cjTE3;{N^KhWPVKX-M1pkl_b$=6372v)OWOk&Hp;BFlwirOvkC z88aqmoMRyZ5NdxH7=bY>(j5NRvnHMpQCnw@c}y(fUiA4{7$oTg3_cm2?LHow?Y{nh zhUDmc;FHX)=rUflb{XC5-tt0 zxpxDZ+*s(*j4X5JV8{&VTQR)^n}&if0SihiiAhg=1bo=ten#*r#JM|_QHy%jeA;i& zCos46HMHbT&5u3z?^C*fJyhQ(2_0SE;p;OG$hS=o^H-x0~H)vj77*J=u|D=CP! zm8~@nWJFzcdKJ1KXwPtj6kh`rBFgSQz4C&c{5E3Uo^v{H*G%kKD|UY6 zbLmFBC0-_vPW7?wkPb~O`&lk*@9tKQ*Aw=Fr}WBDGGdz_?$1OckKX4L+qaY%IA7crzd$m4<5$rgY=_`OzCCT5|^{BC$y<9dqq}t%fD1c>AMZW(TcWUS{C_0HgMrl zEwnPrQ3no@;z0M$f-HOd2L)+m_IbEkR^;%928iox15_c<*M8F-e3IQ z3d&=BX}X6~vdRNhl6O)XTNKak(#QKfc+EX+FyijHadV$#7R4EWVYw9ymJU}^@9~{W zCRvFcGq?-=)nYUK)m=9)>C8%QJa$a2YoiVa94>kv+RK~fc~J0C>`wVjsPh~ z?QlDq1*yO#P_49XGOI%fkLP21Xq~vxVi+FXUZ5YUD%Pznzik}3u?H<}Dytk^h5|*) zE6SyEmXk5WXo-4+Fe`>P3mL#&WuQ{^6$D($=v z$<)YIakN{!ob->tdIsm5HendpEL&p9d9(8Jc}0wVseg<$giEwk#{LQ@@jtedf|Vas z{Z)1w;_2tSboU)&kxsfUuBVD(QcX^zQ(aPA-P+G>S*R~S86Et$pPG&nz*f?MoY~Z; zEiTrRf%MENmg9QPjW10g93#`d?Mmqa8<12%~}NrZ{3j} z?DS)kZ|HU?iHqnBH~+ul-L_J6g-Ng zMt=0+jW72ah^hWr(qO?scb!|QIhNI0VH5YFLbJ9!&-?bqzrW0Sq!o7FuYwn`rXFRr zZNY-700C2FT?L5q^hp@1vY3MobM$;dWL;i&c+0jYGp0GtBKq4FFBw~V{Jif^#oCcM zZxTtqIa_K~v7z+LZKG{Gz6D7L)X#lfc7J>uvHB*D+c6vL}^dgN^ zV~IRpgsI``PPcGe;C8+@eGApfJU$3JwU z2-u*?x1t=F3NKG8R*#;pK&LzYjhC9KoN_}`S?5Sy1#jfjT_#I5nhZJ!t`=LZ0e%=S zpxS7~Sa)~19>w78_SXZ{%dL=p23Srcj=3M`sIiZ;`T@6L&6-hcFl%QdC^Fj4XBgZh z{BQFXYF(gKOSMkKJQJ$pPIsgxXeYK9t3tm3D&V*Dd z91CB9@G~Pb##RgLAAr4Z~Pznz4DGR-Uax(P3C(DYLAnzRm12(w^L~W zOkJxgmOTeBdP5gooe4Dou9v}=L-$iV?A|?tirhBC%LIJKBEHCm7xQDEb(4 zeU9+AS z+6hW%-6L`K8S(L^0mKg-7bTRuKbDMrl02M+)FHI9WT_Ubb@8vCN{tsxAN-D&I%k75+@sdT*YDHL$TIPWnFOo!SFtNdNGYL)#I_ zfbrGGtnq*N(qTiM<%+S_IFPm0AoLi1M=ycHW)=z4oBW<;md)>51viJK9d8G}MuSAK}K%8m$>4pK}f4aBA|>`DA5d(ILfdErC8SB>PxCdcWvl zvFS6VR3=U2jeM(cW> zi3t{z;4@;`7%O~MvH#?y!R4!wC#D6@q=vj-3@_txU8{Xl$a&U`zUSo=mS2LAyt;aKbMPnn;$e_9wk z*2>7Wg;4Y1(2^W(nSeMbTr-y3NgKb>jynvyxlikg42ha;{x2%CyG8c4jLEkhYJGxR z`^<^$c#Dy?dhGZnz|UpWs9s@3b)0Uh^`bt1pzv%0w9QS8@epjTxYWL#|K8{^pC%-z zWf8Pd@@4qyd*=3+oNPqz{OeZB!ZN-n;T$$(?-j_KG^jPl>$I_Y$jtJRA-GF_6>$NaEZs-Osv&Kg zt~|C3^U|$ZodfP9AC=Ghf%(Af6-1lEH3Iiju|`BhXR@V~E?zwGANKga_~8EjGiWc8 z(Sz1E{=+0_B-PUMN_z7?NL#^}Z`XWseVKk_CXFv=2((5yeOEC^x=!_@NDgxJx0qhE zA<-NR0TGKzsmBNO6Ef5=2=t2Zk?S{sXzQ-$U19 z7x|iWQzI+$KpZPFhIti>ivf5P5)C zgEKQ(Cj(eYX^goZUzI5#3tr@Kc#Fv%r25JgPfb6rvChn~)5_&6b9kF#+~D0?DLpuR zAcCB3nvrGtcCgL7{XIDcl6kQXyc1#f2JgRZ({2&YSw1Y7qE_-%cE-NNVqzHCX7>H`)EuUQU*h3teu)=3A0Jx2dQtg`lV`(FHTGFC+P1*c2ikPRQ8e*AS zf6JyOz_9J|)M=zrGIP6j&N;*Ck04Wt-QJq9wiMAtSne)D- zI$6A>r?Zvcro(mEa#3+pu+qUzRLn+4R_B_M&7%YUjGth7t-xV1@O1-cZd*>ErxAKg zf6^nRW(1p`bNKYidYcP@R{UYEF9Gp59}%ipTK-E6ZuIkJ*jHS(F7IL@v5Be^qs}I> zEqmGBE)iBeHLSEv@Ak@%GiCIvK$9op2Z#II8sFI*;myw_fqHkwzY+d6-QKP{TWVy- zUMXPRGRK8oDQz<9*;ARZ8T1mS%m*6Gj>&s#tPsZT5rKOD5&L@``N1RyDr6?JVbl6kHtd8Lio~2MRfqg<|UFV&HS0jkn>5gq7FftCS8n&@qW0r~O7yg?|{* z&D!0-_^Yz;+iw(=j2`u{tGv&fx3EX5&rIibx*k&l+w>L=Lp-ibnZc8XAkKIIkj*$b zGWWmQCGW#7V$&e(zne|cH{#x-KdM*;ztP(#Xq=xYk>cY|3jJrM4_&tC554TLO~S9V z%iZvStyJKea}P%CQgchI;W!7KHwGpjr4Ojrf@h4%C`-k`U|}aBLWogZS*Qc=!A78T&jEqK2jo z+TG5lTR*V>Q?kqsVN1@#f<|hk!~~2!dn*38rTjr6X9q(or`t!Jd+MemD(dPO-uM`Z z6K~g|Z0x46Q)5~j(@unDfNq^ZD3^<38jODVFM@mOw>UE>_p1GN zb|MhFOn<^9+1|0G-O7bxNY5EZcQR99NdK+jKyHkXbbNdZ2iQ^?%w%>9?OI55?984k zyymso$86N>EHj?r8#pOsWY+&8%pN7~uL+KPrD05>?m*aT$%`_~M5js^EY^o-v)A@` z+~W9zF5l>RTD4o6YRxX;{pc~n#^uGc82$>QTzK2+j}E#lI?uRlu)%c$HL?oA6SA$#K$su>OwRj8A554G_qRfm0tFRw z?2aAjj`N`g5x;0!em<0n@CgvbyOskjCx6iBG646k ziWYt5Gp1oPOkc|9@ATf)mCR7JHHKG01im4v87hG#lcEO91TJfHn?iN9>)=3ydGF=- zmPEbVd#y+37$?F!O1tqhDkClAXlqVfx7&Zb!WkT;Gdn<&`Idg~>4Z_-*si|SH z4-lp}htwv9S>wNNvwKEP*w2g^0qvcQ{I+cBD#mV?l}Mx20s)jxLSM|>+eda~6`a_F z5Uev*t{s=0^E+peBNlI^&%-Jsx}Dd%x!9~oFP}V_N`oi=vL=9Y`{c2o8h{Y})&LQ% z5-%fWTT`eRTY`+swb3Q|+K0&1XpG6&Yue2HKRUDNq7FFpqQ@~QZ?I54SuyNf!qS?H zg0oDS7pvb$3ad+`Q({+~(7qV!UwXJ2JM?(X#A`k&Cy8p}K=pzt^}a0cy=QnNnt)K6 ziWy7kw5XbHs#)OXiS~=Tci-dX!TTT#QX{Fhd&Wsuke$nc>l$N)I+WX~Bi}2BiK0o_ z)EMPi9kFsepeieA4`YZjsN&!C!ucnA2=Pyqi%)cXfpZ zGMoInTXU{H&3%cjheo5+N(_!ZqbpwyO9s&=-}#5%^X{{)%5ILESAy5=@d6Dt0n{v|MvJdYwcd-ETDst$a4{HRCGH> zrP#(p94;fC>R($Wp=1PxT+zx=d4OK4d9Hp=FOQLYSdCPxIgIXkz_@yA8hyB@5jyv3 zXRnU*Z*UI%B^RQi^)PTA#FxkqnC*kj%ktHqjXXt>ivz%%sfGf;q9(({tJk{P{Lc>` zzVQ#bvpAfKzqm2QdCjFnXt?2SH$DjuB{jS~b zlITDs9&LQKKMY84(FZZ0_Ads=N&Qk5&q~CV;iLimv&_WasccU3c1gAsQG4j9%tthw zESbE&!nVS)8clp28?WP^1F^8Qkp4ZKU>pA-mi)lQ*hPDWz5`$(i{_{^{(tSJKkzD z@UOeL*)B2YE$Gwy81X7EcOMOQz1_AJxj6Y@ehYhLUB~q1;aYa@gzr>P9I|iJmO#Vq z#N=94=!vlln-M`~1@NyeYKUx?B;D+Pqz{}mj|ujdz;jBFRvMDBlJ5R;umk()KX2pJ z5?I@MD7-|i)PKyv>J^WI!A3)rJ=m}*=I)rS~=XbEvh zP3eS(^(x`YBntPWwN-sr^za>&c2`gmeRXFt{tk*vlAPWmg-rp-X|0&Xlv(V}r-?<( zRQht0`-iq$RO76o@l=!ah&=r{_QQz(Nx>Tk2xskD&@{0OzUylRutIcX-qwbE27H6h z10^TGS0}EInyNTk0$)eMmun@^X06~WK0J>y*u;-R-TB9bL)VL4oNTjJ+yZCeNhIDW z2P%xeg29jGz?n}WquThij&P+`l-=5N?Y7i?$(B;j=diQ#T2v_;S^y;b z0$ePqgL9XM6f-4X9i3|=R9FS~mDdI`_h59R4C$Dk9dC%OFp2EFQQd4{3W(UcKDg0GeYDjvjIufV^fvK&e3O;FvlVTn zFJIjIx1CaM9xSUBn`vbg47LZgy)fd8Hz+>ZxI9EsNa{0lJMzS3WMgTzZdBRR{wEMm zHfPSIj2B+YxF+FtmKG0g&BgQz7p7KTLp4KkO>*_$p&S|B(>EQLYO0$$komInQOAdV zQh0VrPe6Nhds}o zvorgd*qJ??#7!Qk`zYWNis~q3Q`XoM@Y4oSLFctmreK{GC?Og#Q+iw|E zqrYa*Z#4rLo^df+gQzJ5`YaYJM_H*+be21%T9 zwovS%R*ghq{_rqj!d)`A+TZsox#=3?XMVgHPrYqALx{7ut$S>kMjRW`JwP zv_p0%x;u|{cz(UgSK=YP3jN zW8C^d>c-GxBZ4z`0R6wbK*}DY8n4{LF%Mw~B*}MgXF@9x6!WN9?}V}lVY27->6SZd zF5{g+a#T?VKtWI5gshi++U_uK6c*p|moGQ}@&Gz8RPc_$-=5_3jFx;hK;bFbqT#i~ zKO)OnbQXJfXm)-;FeQpikdNir0p0J)^gC;G-5U=1g$Oyz70M?enQFH#xtgVxdq*v# z_uG%5gaS10{(xtve_Ao<oeCPI&HFQ$sGAonxgq1+`+^wI`z^!*o>#S72bH&E5mvqodIaB2`#@4VK& z%A^2_7-9&)(nSBUHtzfd#2O2THI49CLW2JLCsRs1ww7j8in1SVLyeW{cH-Yx&U>p~ z##F4&v|j3gcI3-;VTSd@u!#rF8%j$fso|;F)s5yK(rG~1iJ(nmBHz>xTAx=&F4fi+ z$nDbts>u)u2X@6>zHN=sP9^f6*)09VCz!Ii&e4|3b>ldygKJ47;=@piD&s9k0S&g; zN$UrF9w2tXf|2=3C4v-{xrws*$;m^L>5TlXvrMRVExDLZ9w1ay`g{(-ohkgc0y(^d z#TrNCUF!O=AO@HOMy3kIS1EZhHB)Uy+Ngnv2!ABjkUwxgb^)0F)1cSmXpjbpgEZ)x z`oq_#>s54jg^9_IR69AtS6UH8*Kqv(syUO7(!i`!tv1`@jm_iLVQ8E5I{EfMlz^i1 za?i@;a&n=9=lL5RPqR@bYo_#Hl8DLolGt?6c)u?Qu3R0C3|+>HvF3pHA2ePI`L1S9 zK3)DajiVyPkn0xv3NeI)iBNH#Zp7*s(oWRVG}h(UWMHSBe!R$j87N6|RunP;IgjX`4U8q{>!K5PHo7TW-4EO! ziFc>|jJm%oE2VNlixqB*h<(x??GU4 z37-~GFj3&&VbYk$1*)+~{UD&n%xKT#y|cwUDRZ?FxoPpAL(g({gFLpAiDHr~)e5*z zVFL6GVVVZc;ov)~V)r$xy~^`mfOmJbG`^|vyHoybaijTV$iHRC_D4iYUkr-1H`CrP zxyR%;u_HI#1NL?lvr^Y&k{+4Gw~>+zCB|ipi@Isujoqw_5i|BA5g!11|Kxsq;$!u4 z&(A(I6;r2~xTRM!KMSwgDhlhYx*G6&8@5~^7*jZ|XV*B@7T%sX#9ZuL7dLS{nXi%b zTB7kpF!c368>_#ku!zupelQ8=kGZM>knb!u45KB@jbLS@now19Pxo|h(XJ=xEwOs` zI~l_}e{3DzNc!g^Xw~_L-0ybxP%8FoJDE|8qL;ZvAfGhR8ogdVM!x60T>P04!mK-m z6zRJ2dFM}3>{^Nd@zR!dgrcJ2hyBtB8qwW*C5B4H1Q$@sSZ+%tsh}=)FXJ(>uVRMT zmKG`gcL7ZYGnZPDH!p2Clj9O|fzufGI&gMtjV30{F<<)Y6F>4xi%;x#(pB6D+|6aT zdKWE=+Y}Z$Fp-prN4M2pTzWflF%M^^%|CYWfo{y@9#FLq^km=29qnPLHXPM>EGerEw4WeNH(Yzc-bY)WX?bqtcphbNPJ3Akcb zi@fkEmadMbkRTT8qE%@k4gUoUJY0YTK7@X^`gxqu(|dW8@6o_qqEARFqr`1iVcOGA z0;eUD6gJX)Va=!5XOtUa%T_(GcH9K-RzoN@xmM|&fi}CyULle(R*Wom;e!X6;)Y4( znRuWwp-!Fl&(6J1|FFoN%V_j_tXW990ycQciRB1lA-wfVAZDPCBpwMrQS=W8NKzT%TkOG=1n_i{#sF=5fQ zEv$Ejhcyp!Y#R_BS05ggT(e)2D5oD(R@lxgx%;}9G&(2vU2Uz&oAPC|`^$#yo zW?!J>3e;;n9x?E#YVZg3i%1>D?qk{*jSzAKXYXP2eaFoye4u=bXw&(UzaQ#W5ktus z?1PF=NPMatJooQeFG;Gqxi_WSI(c@W>IS=%yxujoo#rR3m4)fm@{UdX$AbbN928*! z9Zv5=#2bjX+FSu2JZ^HhGzMRDw=>?N1AJ8~J+Uruqy0Ks63A)F%%OBODkv4t*u0MJ zgy{EW)CwKtw@!iEz212g+zT!8ycmy0FeE>6QZ&ii6WcIF$%T|{!GE+7sQEuHGh8|j z&TgOi=PMc%SbW>W)X&Pnn4`Y%YFb)v^edI&OK_*$^DWURT;!_?LzfbTeZ)QvELkIS zs9-FCSC7bpSO4`^JQ*Cm%!r^m?GKv?#|$TTbdn9YTk7AM)!ui5iNXFooGC&Fwg`oaRnUP=Wwi~s;l!);bHyOj461&tScfZuxrjX=((Z}Ua5E)9G zC>kbykP}gRokCU>VQcycRfV)RbZu&`{mF~LpVO;zd=Mv}JXtx(P96bwNXOeJJXhDF zRz0*GU)B3{^|iT)H0fcneq8tU1|Q8Ze|8m-95M_XnHGiu{5Jtq;GlNooGnQ~8T1`- zOC`mU<07_p7-aOv#%X5620ipFgTZ3`dksU*4g-eJ0(?S4IP-o(B*uniZXexk=OVX$ zU97|9I<>!`tdJv!@fYZPFF zZsov`8{QfGLu{g1AbB^qk^uf#P6!%y^5<9ed!xMD?b(mb7MA?2c5ADHVmb+T# z=LFUc^_exY-vrD=9n#MzkTpdsn?tJX2lvjv2fWQ6<>*+Z#seZ)`45m)pc(%J*~Uq0 z&Jb!uNZ2ORsb17ckE~lDS2m^Bl7YvHW@kWx$+EspN?41=)tRMnTx5Vs+~(;?^GdHG zE9=PnRs!>Ir7tm4zZ;=TMrHond4XFSQ;N8~8Kh)yhneK3jveeLF%wCkb`|S8nUZSh zN*`_7hJ|+%gOY;{a$>9uB=ox9TMGyZI~AZS4BpRJT6fPlEs)C0)nNq+=Q3I_UE{A! zS=*rfCO(So-~!K0^CJ?aQ^plohLKtkmHcIWNmST|`C4I}3R1+~HV4>$<4DF5p=X%f z!quOQM;K>`cuyNRP6#Mcyoom*y2Jy)>+g{t>K(a^c&df9*XRSOtwO7`_&pXUXWg*^ z7T^a8?Ne2WeZ$P&P0zLNO)9r`w;4mea45?`lfU^2CjA9!Jo-%7cKwS>3KAPEV2&US z>Ni=_v*-629aSY6?jnP<`&Lah3aCb(eH-%O8!lFcO$F{>-qwpC*4-V>5iAq3YV_S^W*(s3`JAjZ zJK_=6*oKX;?wUP#?IGave)g}Gha(^aJxOCHtHE1oY(DfVv z1h(YE%+3;ZGfrIk;LOdx%%6PsF9S94$rFoSWJEZdw|RUc)*OHcYUp_^U}MeoMX!c# z*Tw$MLWNDn^+me~ufuuA794;1K(iL~cg|C;R_+&@&uS;S#QxuAe;4+r56!O0bpq3DIitS9v*OHT#RT_JbI?-0r28Lf* zh+z+sSjIB`UnW8v{y$rPK>vCGuje_gb@0aqjl-NSwQV2>@H$x&XqJL>8!kvyZDzXt+&FPzb_Mw1eN$z_q7;ynVO}oLv7alVDv!PHq4V zp$teS?ZKUntwx){F~y3;zpO>YTxjM5K7BabSAj`C#LcMF)2s6^YJuj}54|sPoQ?Ct zym~1?)y$q}IU3=!0y+G2QyvT7d#Oz~VzkICw@tDRLSX7=H{e6#z97YomJ0=10SB&k zm9G%$%FPH$?eUdSpr@Hk-^dngyD7Kpj{3(Nmd}28lBW0}05JDjQ!XOqLhH(RW<(*c zK7J0n5t@^*a5q%L?y{+CrRQlU|AAEDIi~lT#!;7E*>g<@gRfo@WkjL1+RNQB@ATiX z=Rr_KMR#40iP0jJxtI_RtBVpGmp%;0v!&Llrz9=;V%X5OKK%UHf5rex)<15~~AifQdafsTbxr2*(<7SMTz z*`;ogMWc^kT1!d8^kO--bevL9c!-?(2*NNQ0nbe92gj%~I@X^Au2}anh0tp%Eq>LI zMsMgcLf+6S9ZqL^AYbQ}sicv5u9>Ul15>%qo<}S9-bEKzy^MDH>bH2o24$sJPfK4T zPID-f(!08ln9*bzh_3Y+xQy6+MY)*NRC+~Nt~uU)_0w!?!?t#aV6q<2jgbu;JG7o| zFgph5wU(Isn0?%ig zQS9!U;(a%PlvnYalpw%{F@+lw1$`wTnEF9YRIQY`8_8>2e|zekR_b0|F<(+@#Z6*3 z!6_%j+fl)49S^6tv4Ft zAJp;R!{`ANaVbg6RDC(iuN;y4LzJHpVW!__xdfb9dRESXCjBjw6Tmpwf(&0y2=f_Ohn4h+BST&JNAs{NGy zaUSQZ?3$5$ZSX*7<{>hF@k9I6d!xI;u63ITRx54j;`Cia8qbR4PnSWlrZ1=k_ua8y zei5Ox9TfPK)hjJ!->(AjcspcWpCzK_k$_4pLBIz+|H-Gn5Cg|Xn8L?RGb#&$7>nS} zO}|kpIKF#^gAb8zl)8xbH?#Bi3}Q@ruymrNm}Zzl1qu1 z!?N%mzy0Zo?m;b&VEglRiQnWMc>6F)KW9ufw132FGhIlN`vTnN?Q6eFtr<08d(3Kz zwKDo>{j`wR2XD2fg%GnzEzB3ImaiH>IXdw;YhL=9)r9R^YKcR>Q|H&~<|m3r z>BwO$8^A~GlCYy3!ji^zzJXM*G04yzhQgF?0(M)q0p=j^y`Kd62b)+jXa8{B$`S76 ztOSY=r1VQ5hdWHOK<{x%uU4G1ZkWYy5f(tBLWAz>{lODKG!8>PFccw`9 z+D7nlq#~OB(W9$~KqN41uw6NKo8Pt3z_Z1YqK|r!EVa42G+*T<%Vwinm0?RA9)+FmP)3TOkJVtDWhhOZj5)k=i)z&hXSTf@blj~9{{ zhlY&$^<^KSV$Mz6L&&dur(Y1xb8>c&VT&suRV=V?5gox6yy|&tI5H>PJ43c%t;n+= zME$8}BgROGx{bWt4SVoofGHuv+lrV>)2vgn^@%=b2vg~IwMErHlCmz>yqg1Yhx8Pb zw=!cvaOWPuXL%mMsN=tf(E~v~7>5$-H(ZIJ#T^tGFQYf`eHCj_J5@u9H!Upzb;A^XUBVRpT}A>b zS|jZ1s<*6ayRzyi-?Zbht~ec%eH*QAQ_Fj+0{v?oFv1ZDt)LGfA8^Rh+3t-Vl0pg; z{*}KQJ1J0gRp%?n%|!M~8JsmFxqd=}W^LHFaD2KC2Iy;z=- z2|m*6qNwQ3%>|ImLDtXCn9(e>wTVZkXYhc8lCh^-Lu@QNl<@`Wu!}Z>=Vu~I5Du$O zAK02+;2}}Is4VB<8(SNF z9oOCZ&TJm-R)o^whVb569n1h1S)yZba?{;*@4Hc*4P;$TJ=2gUsuy^o0dw2pq0?C}m|qj!8pXtR53-7v(ax)1agH4+r7 z4#q9$3ov!WvJA5&(6ApmwwqvXUKb(#J1OrTkG+bRNmOmzt$m`oNgR?pqDDl60 z5lz9vlnZW;caZlrBbUP#H>^6 zlrRdRXYKUyyN9w0F|MqmHhmt_^)wZ8BPb~>1gYOnXa78q7$&8B3M(#1jM=AdHl%k; zqe6UCd@$QFI+Mv2m0nO=h%kn=SW@J9jtMeDgTy|o(4__B*GwTtU#qBbVFsWGV-tYI_jJj>2(X?kKu5jA}N#hR*8 zt8x{nZ7;|IA0{1#op5(%L+^we~|NApPk+6UDV=tA${;f z0g|;^r36KU+_Yho+}_q(Ps<#ob_>{Ql&sj@{XBTB<{UoxNFboRy}H^Js~056&;aHC z@eSFCcTeWP8@gp`)13ZXFb`14zl(vxrP6dYKKJyfQ_RrZy%WvaS{tXQdvW8?uG2%) znt=XIb}AInxEd;ec?YV?ID5N0#7zz|E`co>bawKFh%)=X_Db$0nKP1*J!}}1p_R%t zfpE|9N#ccURsZbgLWT`wdZeiv*a?0FlpgUoaOL9wA;s%_u0$=Dj_mUb38NnpyJfQc zU?fBDGF49}=bo3=CQ84NKd^+Vu}>&vioQKmncyJprD79g!Rv5*|`iu>zoGu9Kq=~VjnygETeM8!W zA{!K2-$$k-a8j2TlWRvM8pY5}CAuvhY}cAmx#{!2%|$e<WN3Lx_pY@2&W<=#*54Tr1m9plJ_+f@1i;WwPQd_eqR&Ru=s&5%=X-(1L*e(T+= z4o*3Kk%$J3)ODhVDsMdYbd;*M(Q^~S0sbfy*xiqe>X{?m;6(#xPk+h!PbqtKlp_n` zipyAm>Y5U}bx=45jrztxRvi~3x5=RU7B_v5nP#u6mOk07H)O0>$}?aj{@220h3~MG z;B%;RR2SE3XeAj=xLJo&=Pa#ZeaJRJvm}3c)UKxNH|`thrOp3=-VuIIS#kPw*bKr9 z(W8B3usx=HmfgB$`i^(Q+3gP_KuXkkaYb!RXi^X(KqypGifW_|F=H<924G@kPwc4% zy{#gmoxY%_lY^n!A!v5UpVr(ppnkvdpj!{UgEB~Bsvr6yZIzK=o5@SfwXeHeu*KZG zKaA9#YFjN~L*H$qwMj$>A9*2EmNEJG+9n`hIM_@&Zgw7!n19T?HIrA7RV_*+#-`Xqmj*iV#-7-3HOp`{L*q(mJpU> zP!yM2>whKq2kw>g`e#xQ=59sUu{V(}jI4F5#`-ioZp%)}a{bi!W!4AItPIPSRtLbV zHfH_KyIPGG?a|}g*UBO%K<{heZTct5=|u;B%6r3Ub+L4Y7-ZYvnQv!>!sqNFWfQV4<4H(Oa$9N+sW4B19YLQp1zs+Q@H+UtH$S=}E%k{> z?FpZJTnS%DJaaTl5~c!h`~z`L&st$m$*{*Vy|nlN7&UU`q-johIX}L$N)3FeI*^wDm4w)Z%3By zN=HeAMw8*linHKNDCh9myHYG}pLCQ}tdIZ!yRb$V?#R*fV{o-JR)t4gxzS$Hr#{uy zFVa(QsoeLlXG<4lMCs?5cZ!=;QhLLqb;6D~d9fo*C=2L&v$lp& zyG+bfrulpwob5Q9n-R{-fC`zayY|?7qMuo~x?G|b+J7NXMhavVaZEh=!e#Dp!rtIe zoEJhAWf;68fkVprFvZ$wg_1sZ_wC$4nchdeYW$=ZSsiEXC|9B)$|{L0d(e`+%7(oC zeWRX03e1IUU8YM2@rc5+Rdh&o)Zb_|7?tqmC)r#rwip};(BTBaKN8#K` z1Jkb^)ui3J7?q~kOL*iQw!N|Hh>rzLzUN7hx(6~aO*@~>P+8r6wREN7@GSSE(7ewY?HzJ4Mp+89A+S&5xw1Q_U*d z-+}s#A2=dua{jc$+_}Q4vW$n*e7lLf=U~K=A!a8%Y;ZO9c-4AYF1*pf5X*A*NK?ow zyMMMX*v4{o5K=EDUzmBLz|3}sRp+fNpS5ES#)}lXym}Zvia!?-!}pr!Rdb(A@ClnP zEVIH=@f5e4DAFtpLR0j5hjCI2Crv^47x0HO0KR|85T;VdmDLteg5dI~-8V##VN8MQ z-Ls`L&OgIJNek!b8dWoJ$7QbmfdCPkDv@u(DwSp+{MYtN?aPJlBvXk_tW+imh7)Fl z;th+?O%ym#9Yi^K@^^xZ9r)2NTLY|+=fkYncvJ(;7F9A)>h*I9H(`3h!Vn^)ZWXkP zYC{%$39HdH7Tr^6!}2^9c^k@@mB*uNMJSOz=c2>X%I~X4pm)DTR!gA(Png!@P>nMOL8=rf|gw56k)Q zz#^8DzrfWvE4Id&mi(<@yKM>Y#2^smG3KUnS3O;AdwiH?So@-K zXqA{3LdzIB7H~xuR-IvZqIO!<(=qx@HK@}cp6G%k>#MTzIeZ<(f&VISVZ{#Yi~r#a zbj2E&N@I=3AqfQ?Z$k>$G|lL7Ndb|K@B#^jj5h>*K0Nv|#*g8bBSuas555e{ z{IXY8VayqSw~5UnGU%b?^Sq-7Tg@&g3=|DayTBISg9gAc$4eD7-V3+b-twZmCz54yge-6COJu;11Ml$Ai5Vx)fxP+JaeaZ4ePt~4+t+(hZ2e@o6 zZr3Xy2gJ>9NLPz)F=cDH-ln!f@y3gO{{cIv66kX~->GQy>E;&XH zD8vL>B-rVHHw7~})0nNXp+xx$%w_Yw7bVO>u5qp9i-OnPu89I%166bx1`mbjl6V6G}Bp}nZ|d>gV!G-@Mn?`{h94{@*?}Yz}TX+GlLQ`yFk6VZ*0Yp|FUB> z=eq@B$1bilvEiL^`B@VF#u>g57FOe(`Nf^yv&1ye(rwh-IzTk?`P=p?pQ_{nIhVj` z1^_GQw+e#>Cg}matX~~ZLeR~y1PWOl5d1fdcSfW-1&IK(=vL$w^!}5^t?nBEe@m?1 zEL95?s+*8cQM%LH$^vcH7*p2F7+OxV6**YV^xQwU_)OsfT%lB(J)KSC_MIx{sY=Mu zqo9?BwJe~*Ri9y1!1Pq-dCxjd--X$h@=CE!Lryl+$TVdC^5L6619ghGRv^7--pEQ8 z@iBgL*9kg3?Nq1T%)n<-CISOOs`(Oe)Z6^{SLt@L06tp6>~H*Q4QQ0fqij^u=yGW% z8-wGZ2gVkysaF-@9j4bU*qIwPMyF=Z-mlUrHOC)3US5+HH!!n8waH?d)JnvZDH2bO50N zZxFN0Um!bcMBec1- zM4goj_U(f5EplZKU=n}xXv;su2_Ic$!#~soP89~0hery*RE+k8^?->e1zwSAF4~un z)2-|$=%0T*z&j7v=&CU!arqmajmvw%8;J?oISgG(>(LT8{u98ZlN`n2NFh2%0ArF#oF^@SLzbO{>z7YRPgSkE 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%0DvqlryBwEPYwG8 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%0D^$2E4(ibx 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

~S$nH(t?_%`8E2I6CUaY-=Qks>DTn~A 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 z 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

LvJcc+t}) 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 diff --git a/spreadsheet/macrofree/network_appdelivery_checklist.en.xlsx b/spreadsheet/macrofree/network_appdelivery_checklist.en.xlsx index 5d1c25a036dce4a7023f96cb201544dfffe6e884..4ab59ea2b4f3b2dee368f5a3f8b77f964c3f92ef 100644 GIT binary patch delta 17960 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 delta 17755 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 Zm+ol-mK9xwz4tUj>GjwS=4wG>{|}1H`>p^0 diff --git a/spreadsheet/macrofree/network_appdelivery_checklist.es.xlsx b/spreadsheet/macrofree/network_appdelivery_checklist.es.xlsx index 4ebba94fd86feac7981e126952709b3860d18d3c..d8c524a28e1e113668eda3488f08147ca12d2467 100644 GIT binary patch delta 18408 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 delta 18203 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 G+5Z81o@i|V diff --git a/spreadsheet/macrofree/network_appdelivery_checklist.ja.xlsx b/spreadsheet/macrofree/network_appdelivery_checklist.ja.xlsx index 074eec8c2b33eebf9c26b63e436a5929d4bb0cad..704e0082d1019e81c7e5abd5c0d14a60eb0ca741 100644 GIT binary patch delta 19093 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 O*gY%8gBUaNo&N(L5i6ts diff --git a/spreadsheet/macrofree/network_appdelivery_checklist.pt.xlsx b/spreadsheet/macrofree/network_appdelivery_checklist.pt.xlsx index 0f44ccff98cba2d11cf01f4a8cb070232ac77eca..bcb2f10326063f51f0bfbbc7e148c1194428df9c 100644 GIT binary patch literal 24108 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 delta 18135 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 diff --git a/spreadsheet/macrofree/network_appdelivery_checklist.zh-Hant.xlsx b/spreadsheet/macrofree/network_appdelivery_checklist.zh-Hant.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..af12041da938fa0490b05ece36e81df51d93e31f GIT binary patch literal 24430 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 KmReV0Ks*4p@qStW literal 0 HcmV?d00001 diff --git a/workbooks/alz_checklist.en_network_counters.json b/workbooks/alz_checklist.en_network_counters.json index b7ec6132f..768ab849e 100644 --- a/workbooks/alz_checklist.en_network_counters.json +++ b/workbooks/alz_checklist.en_network_counters.json @@ -721,7 +721,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" + "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}" } } ] @@ -740,7 +740,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" + "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}" } } ] @@ -778,7 +778,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" } } ] @@ -797,7 +797,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" } } ] @@ -835,7 +835,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" + "resultVal": "{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -854,7 +854,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" + "resultVal": "{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -892,7 +892,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query17Stats:$.Success}" + "resultVal": "{Query22Stats:$.Success}" } } ] @@ -911,7 +911,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query17Stats:$.Total}" + "resultVal": "{Query22Stats:$.Total}" } } ] @@ -949,7 +949,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" + "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}" } } ] @@ -968,7 +968,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" + "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}" } } ] @@ -1006,7 +1006,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}" + "resultVal": "{Query17Stats:$.Success}" } } ] @@ -1025,7 +1025,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}" + "resultVal": "{Query17Stats:$.Total}" } } ] @@ -1063,7 +1063,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}" + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -1082,7 +1082,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}" + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -1120,7 +1120,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}+{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}" + "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query17Stats:$.Total}+{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -1139,7 +1139,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}+{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}" + "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query17Stats:$.Success}+{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -1213,66 +1213,66 @@ "style": "tabs", "links": [ { - "id": "ee2833a1-a75c-46d0-9b99-90995ba5ac2d", + "id": "423273f8-4881-422c-a4eb-eb804eeccc85", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN ({Tab0Success:value}/{Tab0Total:value})", + "linkLabel": "Internet ({Tab0Success:value}/{Tab0Total:value})", "subTarget": "tab0", - "preText": "Virtual WAN", + "preText": "Internet", "style": "primary" }, { - "id": "b73505c5-c836-4793-b4cc-0236113e73e0", + "id": "94a10197-b490-402c-996d-e118234636b6", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid ({Tab1Success:value}/{Tab1Total:value})", + "linkLabel": "Hub and spoke ({Tab1Success:value}/{Tab1Total:value})", "subTarget": "tab1", - "preText": "Hybrid", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "ea28203e-7116-4743-8e69-0d185dfce42a", + "id": "fe53dd71-d712-4df5-947b-fa87f4cf70fb", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke ({Tab2Success:value}/{Tab2Total:value})", + "linkLabel": "Segmentation ({Tab2Success:value}/{Tab2Total:value})", "subTarget": "tab2", - "preText": "Hub and spoke", + "preText": "Segmentation", "style": "primary" }, { - "id": "aa790c2e-0829-4799-83cd-0af9e9c94d32", + "id": "9d162fbe-8d89-4eed-823d-48789f0342dd", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS ({Tab3Success:value}/{Tab3Total:value})", + "linkLabel": "Virtual WAN ({Tab3Success:value}/{Tab3Total:value})", "subTarget": "tab3", - "preText": "PaaS", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "fa4f2eec-c68a-4bad-a29a-c929d9772e42", + "id": "cf481400-6ccd-4b74-a439-34ea7051f62e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation ({Tab4Success:value}/{Tab4Total:value})", + "linkLabel": "IP plan ({Tab4Success:value}/{Tab4Total:value})", "subTarget": "tab4", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "6617fd8e-0e9b-4e9a-9562-06263cd9a56a", + "id": "3692df57-7486-409e-9bd2-c9d5d8aa7a01", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet ({Tab5Success:value}/{Tab5Total:value})", + "linkLabel": "PaaS ({Tab5Success:value}/{Tab5Total:value})", "subTarget": "tab5", - "preText": "Internet", + "preText": "PaaS", "style": "primary" }, { - "id": "41eb4342-7f1b-434c-847b-d5f727276038", + "id": "cecb1cbc-d76e-4b71-a671-223b8d2d350e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan ({Tab6Success:value}/{Tab6Total:value})", + "linkLabel": "Hybrid ({Tab6Success:value}/{Tab6Total:value})", "subTarget": "tab6", - "preText": "IP plan", + "preText": "Hybrid", "style": "primary" } ] @@ -1288,22 +1288,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Internet" }, "name": "tab0title" }, { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext22" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1352,42 +1352,20 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hybrid" - }, - "name": "tab1title" + "name": "query11" }, { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext4" + "name": "querytext12" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1436,20 +1414,20 @@ ] } }, - "name": "query4" + "name": "query12" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext5" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1498,20 +1476,20 @@ ] } }, - "name": "query5" + "name": "query13" }, { "type": 1, "content": { - "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext6" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1560,20 +1538,20 @@ ] } }, - "name": "query6" + "name": "query14" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext7" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1622,20 +1600,20 @@ ] } }, - "name": "query7" + "name": "query15" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, - "name": "querytext8" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1684,16 +1662,16 @@ ] } }, - "name": "query8" + "name": "query16" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab1" + "value": "tab0" }, - "name": "tab1" + "name": "tab0" }, { "type": 12, @@ -1706,7 +1684,7 @@ "content": { "json": "## Hub and spoke" }, - "name": "tab2title" + "name": "tab1title" }, { "type": 1, @@ -1961,9 +1939,9 @@ "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab2" + "value": "tab1" }, - "name": "tab2" + "name": "tab1" }, { "type": 12, @@ -1974,22 +1952,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Segmentation" }, - "name": "tab3title" + "name": "tab2title" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext17" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2038,42 +2016,20 @@ ] } }, - "name": "query17" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Segmentation" - }, - "name": "tab4title" + "name": "query18" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." }, - "name": "querytext18" + "name": "querytext19" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2122,20 +2078,20 @@ ] } }, - "name": "query18" + "name": "query19" }, { "type": 1, "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." + "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." }, - "name": "querytext19" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2184,20 +2140,20 @@ ] } }, - "name": "query19" + "name": "query20" }, { "type": 1, "content": { - "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." + "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." }, - "name": "querytext20" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2246,20 +2202,42 @@ ] } }, - "name": "query20" + "name": "query21" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab2" + }, + "name": "tab2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Virtual WAN" + }, + "name": "tab3title" }, { "type": 1, "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext21" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2308,16 +2286,16 @@ ] } }, - "name": "query21" + "name": "query22" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab3" }, - "name": "tab4" + "name": "tab3" }, { "type": 12, @@ -2328,22 +2306,22 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## IP plan" }, - "name": "tab5title" + "name": "tab4title" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." + "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext11" + "name": "querytext9" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2392,20 +2370,20 @@ ] } }, - "name": "query11" + "name": "query9" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext12" + "name": "querytext10" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2454,20 +2432,42 @@ ] } }, - "name": "query12" + "name": "query10" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab5title" }, { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." }, - "name": "querytext13" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2516,20 +2516,42 @@ ] } }, - "name": "query13" + "name": "query17" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab5" + }, + "name": "tab5" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Hybrid" + }, + "name": "tab6title" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext14" + "name": "querytext4" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2578,20 +2600,20 @@ ] } }, - "name": "query14" + "name": "query4" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." }, - "name": "querytext15" + "name": "querytext5" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2640,20 +2662,20 @@ ] } }, - "name": "query15" + "name": "query5" }, { "type": 1, "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." }, - "name": "querytext16" + "name": "querytext6" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2702,42 +2724,20 @@ ] } }, - "name": "query16" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab5" - }, - "name": "tab5" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## IP plan" - }, - "name": "tab6title" + "name": "query6" }, { "type": 1, "content": { - "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext9" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2786,20 +2786,20 @@ ] } }, - "name": "query9" + "name": "query7" }, { "type": 1, "content": { - "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." }, - "name": "querytext10" + "name": "querytext8" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2848,7 +2848,7 @@ ] } }, - "name": "query10" + "name": "query8" } ] }, diff --git a/workbooks/alz_checklist.en_network_counters_template.json b/workbooks/alz_checklist.en_network_counters_template.json index 147b5451e..175cc4d3c 100644 --- a/workbooks/alz_checklist.en_network_counters_template.json +++ b/workbooks/alz_checklist.en_network_counters_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query11Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query19Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query20Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21Stats\",\n \"type\": 1,\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query21Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}+{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}+{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"ee2833a1-a75c-46d0-9b99-90995ba5ac2d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b73505c5-c836-4793-b4cc-0236113e73e0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"ea28203e-7116-4743-8e69-0d185dfce42a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"aa790c2e-0829-4799-83cd-0af9e9c94d32\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"fa4f2eec-c68a-4bad-a29a-c929d9772e42\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6617fd8e-0e9b-4e9a-9562-06263cd9a56a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"41eb4342-7f1b-434c-847b-d5f727276038\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query11Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query19Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query20Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21Stats\",\n \"type\": 1,\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query21Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query17Stats:$.Total}+{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query17Stats:$.Success}+{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"423273f8-4881-422c-a4eb-eb804eeccc85\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"94a10197-b490-402c-996d-e118234636b6\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"fe53dd71-d712-4df5-947b-fa87f4cf70fb\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"9d162fbe-8d89-4eed-823d-48789f0342dd\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"cf481400-6ccd-4b74-a439-34ea7051f62e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3692df57-7486-409e-9bd2-c9d5d8aa7a01\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"cecb1cbc-d76e-4b71-a671-223b8d2d350e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/alz_checklist.en_network_tabcounters.json b/workbooks/alz_checklist.en_network_tabcounters.json index bab6ab57b..fbde14421 100644 --- a/workbooks/alz_checklist.en_network_tabcounters.json +++ b/workbooks/alz_checklist.en_network_tabcounters.json @@ -70,66 +70,66 @@ "style": "tabs", "links": [ { - "id": "99f6ced1-3725-48ff-9c2b-204ef4a1e6c8", + "id": "583c97e3-f926-47f6-ab42-4a5e243af964", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "Segmentation", "subTarget": "tab0", - "preText": "Internet", + "preText": "Segmentation", "style": "primary" }, { - "id": "48149b48-5e11-4480-9f9c-10930e974e00", + "id": "93772693-c1f3-4f1b-8d48-1c2167755be4", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Hub and spoke", "subTarget": "tab1", - "preText": "Hybrid", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "dbf08e56-7960-459d-bfb6-940ba2d85825", + "id": "5acba310-ace9-40d8-9a68-ae3aafb74ec0", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Internet", "subTarget": "tab2", - "preText": "Virtual WAN", + "preText": "Internet", "style": "primary" }, { - "id": "8db67660-784b-4bd2-8539-1fea260aa601", + "id": "a32c85ef-57f5-4397-b27b-34ca037b2d53", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "PaaS", "subTarget": "tab3", - "preText": "Hub and spoke", + "preText": "PaaS", "style": "primary" }, { - "id": "5b9d8901-5308-4fe2-a83a-ec520bfbdca2", + "id": "5d6f7778-bc1c-484b-baab-133ea74e24f2", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "Virtual WAN", "subTarget": "tab4", - "preText": "PaaS", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "6b75031c-69fe-4b0f-a48f-046c6aa0147c", + "id": "0d7a9748-642c-403f-aed5-bde56e5e9272", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "IP plan", "subTarget": "tab5", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "07aeb181-fba3-42c7-a108-4dceb64b3198", + "id": "35eafa5d-82be-48b2-8d12-eb69ccda7a3e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Hybrid", "subTarget": "tab6", - "preText": "IP plan", + "preText": "Hybrid", "style": "primary" } ] @@ -153,65 +153,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query11FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query12Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query12FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query12Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query13Stats", + "name": "Query18Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -225,9 +169,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query13FullyCompliant", + "name": "Query18FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -237,9 +181,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14Stats", + "name": "Query19Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -253,9 +197,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14FullyCompliant", + "name": "Query19FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -265,9 +209,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15Stats", + "name": "Query20Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -281,9 +225,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15FullyCompliant", + "name": "Query20FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -293,9 +237,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query16Stats", + "name": "Query21Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -309,9 +253,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query16FullyCompliant", + "name": "Query21FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -332,7 +276,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}" + "resultVal": "{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -351,7 +295,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}" + "resultVal": "{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -385,7 +329,7 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Segmentation" }, "customWidth": "50", "name": "tab0title" @@ -426,15 +370,15 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." + "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext11" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -483,20 +427,20 @@ ] } }, - "name": "query11" + "name": "query18" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." }, - "name": "querytext12" + "name": "querytext19" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -545,20 +489,20 @@ ] } }, - "name": "query12" + "name": "query19" }, { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." }, - "name": "querytext13" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -607,20 +551,20 @@ ] } }, - "name": "query13" + "name": "query20" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." }, - "name": "querytext14" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -669,195 +613,43 @@ ] } }, - "name": "query14" - }, - { - "type": 1, - "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." - }, - "name": "querytext15" - }, + "name": "query21" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab0" + }, + "name": "tab0" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ { - "type": 3, + "type": 9, "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", + "version": "KqlParameterItem/1.0", "crossComponentResources": [ "{Subscription}" ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query15" - }, - { - "type": 1, - "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." - }, - "name": "querytext16" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query16" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "crossComponentResources": [ - "{Subscription}" - ], - "parameters": [ - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query4Stats", - "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query4FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query5Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 + "parameters": [ + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query0Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 }, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources" @@ -865,9 +657,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5FullyCompliant", + "name": "Query0FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -877,9 +669,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6Stats", + "name": "Query1Stats", "type": 1, - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -893,9 +685,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6FullyCompliant", + "name": "Query1FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -905,9 +697,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7Stats", + "name": "Query2Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -921,9 +713,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7FullyCompliant", + "name": "Query2FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -933,9 +725,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8Stats", + "name": "Query3Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -949,9 +741,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8FullyCompliant", + "name": "Query3FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -972,7 +764,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" } } ] @@ -991,7 +783,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" } } ] @@ -1025,7 +817,7 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## Hub and spoke" }, "customWidth": "50", "name": "tab1title" @@ -1066,77 +858,15 @@ { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." - }, - "name": "querytext4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query4" - }, - { - "type": 1, - "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." }, - "name": "querytext5" + "name": "querytext0" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1185,20 +915,20 @@ ] } }, - "name": "query5" + "name": "query0" }, { "type": 1, "content": { - "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." }, - "name": "querytext6" + "name": "querytext1" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1247,20 +977,20 @@ ] } }, - "name": "query6" + "name": "query1" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." }, - "name": "querytext7" + "name": "querytext2" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1309,20 +1039,20 @@ ] } }, - "name": "query7" + "name": "query2" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information." }, - "name": "querytext8" + "name": "querytext3" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1371,7 +1101,7 @@ ] } }, - "name": "query8" + "name": "query3" } ] }, @@ -1399,9 +1129,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22Stats", + "name": "Query11Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -1415,9 +1145,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22FullyCompliant", + "name": "Query11FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1427,199 +1157,37 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Success", + "name": "Query12Stats", "type": 1, + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab2Total", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" - } - } - ] + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" }, { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Percent", + "name": "Query12FullyCompliant", "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query12Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "round(100*{Tab2Success}/{Tab2Total})" - } - } - ] - } - ], - "style": "pills", - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - "name": "TabInvisibleParameters" - }, - { - "type": 1, - "content": { - "json": "## Virtual WAN" - }, - "customWidth": "50", - "name": "tab2title" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab2Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", - "size": 3, - "queryType": 8, - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 4, - "formatOptions": { - "min": 0, - "max": 100, - "palette": "redGreen" - }, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - "subtitleContent": { - "columnMatch": "Column2" + "queryType": 8 }, - "showBorder": true - } - }, - "customWidth": "50", - "name": "TabPercentTile" - }, - { - "type": 1, - "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." - }, - "name": "querytext22" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab2" - }, - "name": "tab2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "crossComponentResources": [ - "{Subscription}" - ], - "parameters": [ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0Stats", + "name": "Query13Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -1633,9 +1201,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0FullyCompliant", + "name": "Query13FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1645,9 +1213,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query1Stats", + "name": "Query14Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -1661,9 +1229,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query1FullyCompliant", + "name": "Query14FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1673,9 +1241,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2Stats", + "name": "Query15Stats", "type": 1, - "query": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -1689,9 +1257,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2FullyCompliant", + "name": "Query15FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1701,9 +1269,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query3Stats", + "name": "Query16Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -1717,9 +1285,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query3FullyCompliant", + "name": "Query16FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1729,7 +1297,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Success", + "name": "Tab2Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1740,7 +1308,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" + "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}" } } ] @@ -1748,7 +1316,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Total", + "name": "Tab2Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1759,7 +1327,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" + "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}" } } ] @@ -1767,7 +1335,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Percent", + "name": "Tab2Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1778,7 +1346,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab3Success}/{Tab3Total})" + "resultVal": "round(100*{Tab2Success}/{Tab2Total})" } } ] @@ -1793,16 +1361,16 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## Internet" }, "customWidth": "50", - "name": "tab3title" + "name": "tab2title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab2Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -1834,15 +1402,15 @@ { "type": 1, "content": { - "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext0" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1891,20 +1459,20 @@ ] } }, - "name": "query0" + "name": "query11" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext1" + "name": "querytext12" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1953,20 +1521,20 @@ ] } }, - "name": "query1" + "name": "query12" }, { "type": 1, "content": { - "json": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext2" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2015,20 +1583,20 @@ ] } }, - "name": "query2" + "name": "query13" }, { "type": 1, "content": { - "json": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information." + "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext3" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2077,16 +1645,140 @@ ] } }, - "name": "query3" - } + "name": "query14" + }, + { + "type": 1, + "content": { + "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + }, + "name": "querytext15" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query15" + }, + { + "type": 1, + "content": { + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + }, + "name": "querytext16" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query16" + } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab3" + "value": "tab2" }, - "name": "tab3" + "name": "tab2" }, { "type": 12, @@ -2133,7 +1825,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Success", + "name": "Tab3Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2152,7 +1844,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Total", + "name": "Tab3Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2171,7 +1863,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Percent", + "name": "Tab3Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2182,7 +1874,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab4Success}/{Tab4Total})" + "resultVal": "round(100*{Tab3Success}/{Tab3Total})" } } ] @@ -2200,13 +1892,13 @@ "json": "## PaaS" }, "customWidth": "50", - "name": "tab4title" + "name": "tab3title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -2302,9 +1994,9 @@ "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab3" }, - "name": "tab4" + "name": "tab3" }, { "type": 12, @@ -2323,93 +2015,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query18Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query18FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query19Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query19FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query20Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query20FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query21Stats", + "name": "Query22Stats", "type": 1, - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -2423,9 +2031,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21FullyCompliant", + "name": "Query22FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2435,7 +2043,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Success", + "name": "Tab4Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2446,7 +2054,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" + "resultVal": "{Query22Stats:$.Success}" } } ] @@ -2454,7 +2062,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Total", + "name": "Tab4Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2465,7 +2073,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" + "resultVal": "{Query22Stats:$.Total}" } } ] @@ -2473,7 +2081,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Percent", + "name": "Tab4Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2484,7 +2092,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab5Success}/{Tab5Total})" + "resultVal": "round(100*{Tab4Success}/{Tab4Total})" } } ] @@ -2499,16 +2107,16 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## Virtual WAN" }, "customWidth": "50", - "name": "tab5title" + "name": "tab4title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -2540,201 +2148,15 @@ { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." - }, - "name": "querytext18" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query18" - }, - { - "type": 1, - "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." - }, - "name": "querytext19" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query19" - }, - { - "type": 1, - "content": { - "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." - }, - "name": "querytext20" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query20" - }, - { - "type": 1, - "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext21" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2783,16 +2205,16 @@ ] } }, - "name": "query21" + "name": "query22" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab4" }, - "name": "tab5" + "name": "tab4" }, { "type": 12, @@ -2867,7 +2289,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Success", + "name": "Tab5Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2886,7 +2308,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Total", + "name": "Tab5Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2905,7 +2327,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Percent", + "name": "Tab5Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2916,7 +2338,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab6Success}/{Tab6Total})" + "resultVal": "round(100*{Tab5Success}/{Tab5Total})" } } ] @@ -2934,13 +2356,13 @@ "json": "## IP plan" }, "customWidth": "50", - "name": "tab6title" + "name": "tab5title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab6Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -3095,6 +2517,584 @@ } ] }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab5" + }, + "name": "tab5" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "crossComponentResources": [ + "{Subscription}" + ], + "parameters": [ + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query4Stats", + "type": 1, + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query4FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query5Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query5FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query6Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query6FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query7Stats", + "type": 1, + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query7FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query8Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query8FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab6Success", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + } + } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab6Total", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + } + } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab6Percent", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "round(100*{Tab6Success}/{Tab6Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + "name": "TabInvisibleParameters" + }, + { + "type": 1, + "content": { + "json": "## Hybrid" + }, + "customWidth": "50", + "name": "tab6title" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab6Percent}\\\", \\\"Column2\\\": \\\"Percent of successful checks\\\"}\",\"transformers\":null}", + "size": 3, + "queryType": 8, + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 4, + "formatOptions": { + "min": 0, + "max": 100, + "palette": "redGreen" + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true + } + }, + "customWidth": "50", + "name": "TabPercentTile" + }, + { + "type": 1, + "content": { + "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + }, + "name": "querytext4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query4" + }, + { + "type": 1, + "content": { + "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + }, + "name": "querytext5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query5" + }, + { + "type": 1, + "content": { + "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + }, + "name": "querytext6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query6" + }, + { + "type": 1, + "content": { + "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + }, + "name": "querytext7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query7" + }, + { + "type": 1, + "content": { + "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + }, + "name": "querytext8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query8" + } + ] + }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", diff --git a/workbooks/alz_checklist.en_network_tabcounters_template.json b/workbooks/alz_checklist.en_network_tabcounters_template.json index ed95b3277..69354f98a 100644 --- a/workbooks/alz_checklist.en_network_tabcounters_template.json +++ b/workbooks/alz_checklist.en_network_tabcounters_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"99f6ced1-3725-48ff-9c2b-204ef4a1e6c8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"48149b48-5e11-4480-9f9c-10930e974e00\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"dbf08e56-7960-459d-bfb6-940ba2d85825\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8db67660-784b-4bd2-8539-1fea260aa601\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5b9d8901-5308-4fe2-a83a-ec520bfbdca2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab4\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6b75031c-69fe-4b0f-a48f-046c6aa0147c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"07aeb181-fba3-42c7-a108-4dceb64b3198\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab6\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query11Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab2title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab2Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab4title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab4Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query19Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query20Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21Stats\",\n \"type\": 1,\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query21Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab5title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab5Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab6title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab6Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"583c97e3-f926-47f6-ab42-4a5e243af964\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"93772693-c1f3-4f1b-8d48-1c2167755be4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5acba310-ace9-40d8-9a68-ae3aafb74ec0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a32c85ef-57f5-4397-b27b-34ca037b2d53\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab3\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5d6f7778-bc1c-484b-baab-133ea74e24f2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0d7a9748-642c-403f-aed5-bde56e5e9272\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab5\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"35eafa5d-82be-48b2-8d12-eb69ccda7a3e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query19Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query20Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21Stats\",\n \"type\": 1,\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query21Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query11Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab2title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab2Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query17Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab4title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab4Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab5title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab5Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab6title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab6Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/alz_checklist.en_network_workbook.json b/workbooks/alz_checklist.en_network_workbook.json index 8329e8280..fa83d2201 100644 --- a/workbooks/alz_checklist.en_network_workbook.json +++ b/workbooks/alz_checklist.en_network_workbook.json @@ -70,7 +70,7 @@ "style": "tabs", "links": [ { - "id": "cd3aca28-b016-4a24-947a-643a4c2af387", + "id": "7cbddd4c-95a7-4924-b77d-91aec1d6ef03", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Hub and spoke", @@ -79,57 +79,57 @@ "style": "primary" }, { - "id": "8edf1cbb-92f0-4e3f-bfd2-8aea041199bf", + "id": "bcd13990-3f88-44b1-902e-3d67522126fd", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Hybrid", "subTarget": "tab1", - "preText": "Virtual WAN", + "preText": "Hybrid", "style": "primary" }, { - "id": "eb378e76-01d3-4a51-8062-e160093995e3", + "id": "319600cf-3745-4036-b93b-138cbe2b23c7", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "IP plan", "subTarget": "tab2", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "70af1a96-4073-4b33-a445-e6455bd95d2c", + "id": "25a691d6-f03a-4129-a10b-1bbc7e3701be", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Internet", "subTarget": "tab3", - "preText": "Hybrid", + "preText": "Internet", "style": "primary" }, { - "id": "05c56fe5-649f-40e6-8535-f06d61541ed8", + "id": "4a8d73e3-ce33-4f29-ba5e-2b1aca198c22", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Segmentation", "subTarget": "tab4", - "preText": "IP plan", + "preText": "Segmentation", "style": "primary" }, { - "id": "3d874acc-5197-4c39-9f23-4ab27e25f2f4", + "id": "887d8919-d790-4be3-8d9b-f166ba7a9bff", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "Virtual WAN", "subTarget": "tab5", - "preText": "PaaS", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "5f031f55-207d-4f9a-bc7b-1450ed966670", + "id": "d7de88f8-f081-4ba7-bd11-c2ab4509d343", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "PaaS", "subTarget": "tab6", - "preText": "Internet", + "preText": "PaaS", "style": "primary" } ] @@ -415,22 +415,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Hybrid" }, "name": "tab1title" }, { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext22" + "name": "querytext4" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -479,42 +479,20 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab1" - }, - "name": "tab1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Segmentation" - }, - "name": "tab2title" + "name": "query4" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." }, - "name": "querytext18" + "name": "querytext5" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -563,20 +541,20 @@ ] } }, - "name": "query18" + "name": "query5" }, { "type": 1, "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." + "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." }, - "name": "querytext19" + "name": "querytext6" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -625,20 +603,20 @@ ] } }, - "name": "query19" + "name": "query6" }, { "type": 1, "content": { - "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." + "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext20" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -687,20 +665,20 @@ ] } }, - "name": "query20" + "name": "query7" }, { "type": 1, "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." }, - "name": "querytext21" + "name": "querytext8" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -749,16 +727,16 @@ ] } }, - "name": "query21" + "name": "query8" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab2" + "value": "tab1" }, - "name": "tab2" + "name": "tab1" }, { "type": 12, @@ -769,22 +747,22 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## IP plan" }, - "name": "tab3title" + "name": "tab2title" }, { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext4" + "name": "querytext9" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -833,20 +811,20 @@ ] } }, - "name": "query4" + "name": "query9" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext5" + "name": "querytext10" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -895,20 +873,42 @@ ] } }, - "name": "query5" + "name": "query10" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab2" + }, + "name": "tab2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Internet" + }, + "name": "tab3title" }, { "type": 1, "content": { - "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext6" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -957,20 +957,20 @@ ] } }, - "name": "query6" + "name": "query11" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext7" + "name": "querytext12" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1019,20 +1019,20 @@ ] } }, - "name": "query7" + "name": "query12" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext8" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1081,42 +1081,20 @@ ] } }, - "name": "query8" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## IP plan" - }, - "name": "tab4title" + "name": "query13" }, { "type": 1, "content": { - "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext9" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1165,20 +1143,20 @@ ] } }, - "name": "query9" + "name": "query14" }, { "type": 1, "content": { - "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext10" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1227,42 +1205,20 @@ ] } }, - "name": "query10" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab4" - }, - "name": "tab4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## PaaS" - }, - "name": "tab5title" + "name": "query15" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, - "name": "querytext17" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1311,16 +1267,16 @@ ] } }, - "name": "query17" + "name": "query16" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab3" }, - "name": "tab5" + "name": "tab3" }, { "type": 12, @@ -1331,22 +1287,22 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Segmentation" }, - "name": "tab6title" + "name": "tab4title" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." + "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext11" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1395,20 +1351,20 @@ ] } }, - "name": "query11" + "name": "query18" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." }, - "name": "querytext12" + "name": "querytext19" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1457,20 +1413,20 @@ ] } }, - "name": "query12" + "name": "query19" }, { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." }, - "name": "querytext13" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1519,20 +1475,20 @@ ] } }, - "name": "query13" + "name": "query20" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." }, - "name": "querytext14" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1581,20 +1537,42 @@ ] } }, - "name": "query14" + "name": "query21" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Virtual WAN" + }, + "name": "tab5title" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext15" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1643,20 +1621,42 @@ ] } }, - "name": "query15" + "name": "query22" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab5" + }, + "name": "tab5" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab6title" }, { "type": 1, "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." }, - "name": "querytext16" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1705,7 +1705,7 @@ ] } }, - "name": "query16" + "name": "query17" } ] }, diff --git a/workbooks/alz_checklist.en_network_workbook_template.json b/workbooks/alz_checklist.en_network_workbook_template.json index 48dd01399..a6d6c7ed7 100644 --- a/workbooks/alz_checklist.en_network_workbook_template.json +++ b/workbooks/alz_checklist.en_network_workbook_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"cd3aca28-b016-4a24-947a-643a4c2af387\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8edf1cbb-92f0-4e3f-bfd2-8aea041199bf\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"eb378e76-01d3-4a51-8062-e160093995e3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"70af1a96-4073-4b33-a445-e6455bd95d2c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"05c56fe5-649f-40e6-8535-f06d61541ed8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab4\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3d874acc-5197-4c39-9f23-4ab27e25f2f4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5f031f55-207d-4f9a-bc7b-1450ed966670\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"7cbddd4c-95a7-4924-b77d-91aec1d6ef03\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"bcd13990-3f88-44b1-902e-3d67522126fd\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"319600cf-3745-4036-b93b-138cbe2b23c7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab2\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"25a691d6-f03a-4129-a10b-1bbc7e3701be\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"4a8d73e3-ce33-4f29-ba5e-2b1aca198c22\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"887d8919-d790-4be3-8d9b-f166ba7a9bff\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d7de88f8-f081-4ba7-bd11-c2ab4509d343\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab6\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/network_appdelivery_checklist.en_counters_workbook.json b/workbooks/network_appdelivery_checklist.en_counters_workbook.json index 31dac2961..b671fce7b 100644 --- a/workbooks/network_appdelivery_checklist.en_counters_workbook.json +++ b/workbooks/network_appdelivery_checklist.en_counters_workbook.json @@ -124,7 +124,7 @@ "version": "KqlParameterItem/1.0", "name": "Query2Stats", "type": 1, - "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -367,7 +367,7 @@ "style": "tabs", "links": [ { - "id": "77049e08-d295-49a2-b6ba-b08d387b08d8", + "id": "bedcb024-7bab-488c-9eda-25029e44dbd3", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})", @@ -519,7 +519,7 @@ { "type": 1, "content": { - "json": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." + "json": "Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." }, "name": "querytext2" }, @@ -527,7 +527,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", diff --git a/workbooks/network_appdelivery_checklist.en_counters_workbook_template.json b/workbooks/network_appdelivery_checklist.en_counters_workbook_template.json index 953d7f550..1d89e1741 100644 --- a/workbooks/network_appdelivery_checklist.en_counters_workbook_template.json +++ b/workbooks/network_appdelivery_checklist.en_counters_workbook_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Application Delivery Networking\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"77049e08-d295-49a2-b6ba-b08d387b08d8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Application Delivery Networking\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"bedcb024-7bab-488c-9eda-25029e44dbd3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/network_appdelivery_checklist.en_workbook.json b/workbooks/network_appdelivery_checklist.en_workbook.json index ae864ccd9..5361bc397 100644 --- a/workbooks/network_appdelivery_checklist.en_workbook.json +++ b/workbooks/network_appdelivery_checklist.en_workbook.json @@ -70,7 +70,7 @@ "style": "tabs", "links": [ { - "id": "c74e73d7-5d8a-4ceb-882b-c4fab4c1a8af", + "id": "aa013ab8-05e1-453b-a73c-8f3457465dd0", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity", @@ -222,7 +222,7 @@ { "type": 1, "content": { - "json": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." + "json": "Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." }, "name": "querytext2" }, @@ -230,7 +230,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", diff --git a/workbooks/network_appdelivery_checklist.en_workbook_template.json b/workbooks/network_appdelivery_checklist.en_workbook_template.json index 60d1660df..bf039aeed 100644 --- a/workbooks/network_appdelivery_checklist.en_workbook_template.json +++ b/workbooks/network_appdelivery_checklist.en_workbook_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Application Delivery Networking\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"c74e73d7-5d8a-4ceb-882b-c4fab4c1a8af\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Application Delivery Networking\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"aa013ab8-05e1-453b-a73c-8f3457465dd0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your Application Gateways v2 should be deployed in subnets with IP prefixes equal or larger than /24. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | mv-expand subnets.properties.addressPrefixes | project id, subnetId = tostring(subnets.id), prefix1 = subnets.properties.addressPrefix, prefix2 = subnets.properties.addressPrefixes | mv-expand prefix2 | extend prefix = iff(isnotnull(prefix1), prefix1, prefix2) | extend subnetPrefixLength = split(prefix, '/')[1])on subnetId | extend compliant = (subnetPrefixLength <= 24 or subnetPrefixLength == 64) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]"

+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 CW4lWL literal 284940 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