diff --git a/checklists/aks_checklist.en.json b/checklists/aks_checklist.en.json index 96b09524d..74f042b0c 100644 --- a/checklists/aks_checklist.en.json +++ b/checklists/aks_checklist.en.json @@ -1400,6 +1400,6 @@ "metadata": { "name": "Azure AKS Review", "state": "GA", - "timestamp": "October 09, 2023" + "timestamp": "October 20, 2023" } } \ No newline at end of file diff --git a/checklists/aks_checklist.es.json b/checklists/aks_checklist.es.json index e4b2dcef3..b4f8ff164 100644 --- a/checklists/aks_checklist.es.json +++ b/checklists/aks_checklist.es.json @@ -1350,7 +1350,7 @@ "metadata": { "name": "Azure AKS Review", "state": "GA", - "timestamp": "October 09, 2023" + "timestamp": "October 20, 2023" }, "severities": [ { diff --git a/checklists/aks_checklist.ja.json b/checklists/aks_checklist.ja.json index c1480af5d..edbb58305 100644 --- a/checklists/aks_checklist.ja.json +++ b/checklists/aks_checklist.ja.json @@ -1350,7 +1350,7 @@ "metadata": { "name": "Azure AKS Review", "state": "GA", - "timestamp": "October 09, 2023" + "timestamp": "October 20, 2023" }, "severities": [ { diff --git a/checklists/aks_checklist.ko.json b/checklists/aks_checklist.ko.json index a48258eba..6a67f28f5 100644 --- a/checklists/aks_checklist.ko.json +++ b/checklists/aks_checklist.ko.json @@ -1350,7 +1350,7 @@ "metadata": { "name": "Azure AKS Review", "state": "GA", - "timestamp": "October 09, 2023" + "timestamp": "October 20, 2023" }, "severities": [ { diff --git a/checklists/aks_checklist.pt.json b/checklists/aks_checklist.pt.json index ce7aee50b..a7dc458cc 100644 --- a/checklists/aks_checklist.pt.json +++ b/checklists/aks_checklist.pt.json @@ -1350,7 +1350,7 @@ "metadata": { "name": "Azure AKS Review", "state": "GA", - "timestamp": "October 09, 2023" + "timestamp": "October 20, 2023" }, "severities": [ { diff --git a/checklists/checklist.en.master.json b/checklists/checklist.en.master.json index 5798334d2..b2c82d41c 100644 --- a/checklists/checklist.en.master.json +++ b/checklists/checklist.en.master.json @@ -1,1737 +1,3487 @@ { "items": [ { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/data-loss-prevention", - "severity": "High", - "subcategory": "Data Protection", - "text": "Disable Azure Container Registry image export" + "category": "BCDR", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "services": [ + "Storage", + "Backup", + "AVS" + ], + "severity": "Medium", + "subcategory": "Backup", + "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-azure-policy", - "severity": "High", - "subcategory": "Data Protection", - "text": "Enable Azure Policies for Azure Container Registry" + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Microsoft backup service", + "guid": "fc8af7a1-c724-e255-c18d-4ca22a6f27f0", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "services": [ + "Backup", + "AVS" + ], + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Use MABS as your backup solution" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-tutorial-sign-build-push", - "severity": "High", - "subcategory": "Data Protection", - "text": "Sign and Verify containers with notation (Notary v2)" + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Best practice - this is Backup, not disaster recovery", + "guid": "be28860f-3d29-a79a-1a0e-36f1b23b36ae", + "link": "Best practice to deploy backup in the same region as your AVS deployment", + "services": [ + "ASR", + "Backup", + "AVS" + ], + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/tutorial-customer-managed-keys", + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Best practice - in case AVS is unavailable", + "guid": "4d2f79a5-4ccf-0dfc-557c-49619b99a540", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "services": [ + "AVS" + ], "severity": "Medium", - "subcategory": "Data Protection", - "text": "Encrypt registry with a customer managed key" + "subcategory": "Business Continuity", + "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Use Managed Identities to connect instead of Service Principals" + "category": "BCDR", + "checklist": "Azure VMware Solution 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", + "link": "Will Disaster Recovery Site Recovery, HCX Disaster Recovery, SRM or back tools be used?", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Business Continuity", + "text": "Escalation process with Microsoft in the event of a regional DR" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable local authentication for management plane access" + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Compare SRM with HCX", + "guid": "f379436d-3051-daa0-01fb-dc4e0e04d677", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/disaster-recovery-using-vmware-site-recovery-manager", + "services": [ + "ASR", + "AVS" + ], + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-roles?tabs=azure-cli", - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Assign AcrPull & AcrPush RBAC roles rather than granting Administrative access to identity principals" + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Recovery into Azure instead of Vmware solution", + "guid": "367f71d8-3cf6-51a0-91a5-3db3d570cc19", + "link": "https://docs.microsoft.com/en-us/azure/site-recovery/avs-tutorial-prepare-azure", + "services": [ + "ASR", + "AVS" + ], + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Disable anonymous pull/push access", - "guid": "e338997e-41c7-47d7-acf6-a62a1194956d", - "link": "https://learn.microsoft.com/azure/container-registry/anonymous-pull-access#configure-anonymous-pull-access", + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Avoid manual tasks as much as possible", + "guid": "ee02ada0-1887-bb3a-b84c-423f45a09ef9", + "link": "https://docs.microsoft.com/en-us/azure/site-recovery/avs-tutorial-prepare-azure", + "services": [ + "ASR", + "AVS" + ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Disable Anonymous pull access" + "subcategory": "Disaster Recovery", + "text": "Use Automated recovery plans with either of the Disaster solutions," }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication?tabs=azure-cli", - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Disable repository-scoped access tokens" + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Any other datacenter in the same region", + "guid": "0c2b74e5-9c28-780d-1df3-12d3de4aaa76", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/connect-multiple-private-clouds-same-region", + "services": [ + "ASR", + "AVS" + ], + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Configure a secondary disaster recovery environment" }, { - "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", - "severity": "High", - "subcategory": "Identity and Access Control", - "text": "Deploy images from a trusted environment" + "category": "BCDR", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "services": [ + "ASR", + "AVS" + ], + "severity": "Medium", + "subcategory": "Disaster Recovery", + "text": "Assign IP ranges unique to each region" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-enable-conditional-access-policy", + "category": "BCDR", + "checklist": "Azure VMware Solution 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", + "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": [ + "ASR", + "ExpressRoute", + "NVA", + "AVS" + ], "severity": "Medium", - "subcategory": "Identity and Access Control", - "text": "Disable Azure ARM audience tokens for authentication" + "subcategory": "Disaster Recovery", + "text": "Use Global Reach between DR regions" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/monitor-service", + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible", + "guid": "70cfbddc-d3d4-9188-77c8-1cabaefef646", + "link": "General recommendation for storing encryption keys.", + "services": [ + "AVS", + "AKV" + ], "severity": "Medium", - "subcategory": "Logging and Monitoring", - "text": "Enable diagnostics logging" + "subcategory": "Encryption", + "text": "Use Azure Key Vault with in-guest encryption " }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", + "category": "BCDR", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/concepts-storage#data-at-rest-encryption", + "services": [ + "SQL", + "AVS" + ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Control inbound network access with Private Link" + "subcategory": "Encryption", + "text": "Use in-guest encryption" }, { - "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", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-access-selected-networks#disable-public-network-access", + "category": "BCDR", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/key-vault/general/authentication", + "services": [ + "ExpressRoute", + "AVS", + "AKV" + ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Disable Public Network access" + "subcategory": "Encryption", + "text": "Keyvault use for secrets" }, { - "category": "Security", - "checklist": "Azure Container Registry Security Review", - "description": "Only the ACR Premium SKU supports Private Link access", - "guid": "fc833934-8b26-42d6-ac5f-512925498f6d", - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-skus", + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Older OS security patching configured for workloads running on Azure VMware Solution are eligible for ESU", + "guid": "4f8b20e9-a2a1-f80f-af9b-8aa3b26dca08", + "link": "https://docs.microsoft.com/en-us/windows-server/get-started/extended-security-updates-deploy", + "services": [ + "AVS" + ], "severity": "Medium", - "subcategory": "Network Security", - "text": "Use an Azure Container Registry SKU that supports Private Link (Premium SKU)" + "subcategory": "Extended support", + "text": "Ensure extended security update support " }, { - "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", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", - "severity": "Low", - "subcategory": "Network Security", - "text": "Enable Defender for Containers to scan Azure Container Registry for vulnerabilities" + "category": "BCDR", + "checklist": "Azure VMware Solution Checklist", + "description": "Use a SIEM/SOAR", + "guid": "9bb22fec-4d00-3b95-7136-e225d0f5c63a", + "link": "https://learn.microsoft.com/en-us/azure/sentinel/overview", + "services": [ + "Sentinel", + "AVS" + ], + "severity": "Medium", + "subcategory": "Investigation", + "text": "Enable Azure Sentinel or 3rd party SIEM " + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "An ExR Global Reach connection will be established to the ExR circuit, no other connections", + "guid": "a2c12df2-07fa-3edd-2cec-fda0b55fb952", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "services": [ + "VWAN", + "AVS" + ], + "severity": "Medium", + "subcategory": "Direct (no vWAN, no H&S)", + "text": "Global Reach to ExR circuit - no Azure resources" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Use ExR to connect on-premises (other) location to Azure", + "guid": "f62ce162-ba5a-429d-674e-fafa1af5f706", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/tutorial-expressroute-global-reach-private-cloud", + "services": [ + "ExpressRoute", + "AVS" + ], + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Connect to Azure using ExR" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Use the migration assesment tool and timeline to determine bandwidth required", + "guid": "cf01c73b-1247-0a7a-740c-e1ea29bda340", + "link": "https://learn.microsoft.com/en-us/azure/expressroute/expressroute-introduction", + "services": [ + "ExpressRoute", + "AVS" + ], + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Bandwidth sizing" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "What traffic is routed through a firewall, what goes directly into Azure", + "guid": "aab216ee-8941-315e-eada-c7e1f2243bd1", + "link": "https://learn.microsoft.com/en-us/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "services": [ + "ExpressRoute", + "AVS" + ], + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Traffic routing " + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "AVS to ExR circuit, no traffic inspection", + "guid": "1f956e45-f62d-5c95-3a95-3bab718907f8", + "link": "https://learn.microsoft.com/en-us/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "services": [ + "ExpressRoute", + "AVS" + ], + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Global Reach " + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Name of the vNet and a unique address space /24 minimum", + "guid": "91f7a87b-21ac-d712-959c-8df2ba034253", + "link": "https://learn.microsoft.com/en-us/azure/virtual-network/quick-create-portal", + "services": [ + "VNet", + "AVS" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "vNet name & address space" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Subnet must be called GatewaySubnet", + "guid": "58a027e2-f37f-b540-45d5-e44843aba26b", + "link": "https://learn.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "services": [ + "VNet", + "VPN", + "AVS", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "Gateway subnet" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Create a VPN gateway on the hub Gateway subnet", + "guid": "d4806549-0913-3e79-b580-ac2d3706e65a", + "link": "https://learn.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "services": [ + "VNet", + "VPN", + "AVS", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "VPN Gateway" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Create an ExR Gateway in the hub Gateway subnet.", + "guid": "864d7a8b-7016-c769-a717-61af6bfb73d2", + "link": "https://learn.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings", + "services": [ + "VNet", + "VPN", + "AVS", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "ExR Gateway" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "How will Internet traffic be routes, Az Firewall, NVA, Secure Hub, On-Premises firewall?", + "guid": "cc2e11b9-7911-7da1-458c-d7fcef794aad", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/enable-public-internet-access", + "services": [ + "NVA", + "AVS" + ], + "severity": "Medium", + "subcategory": "Internet", + "text": "Egress point" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Allow remote connectivity to AVS via the portal, specifically to vCenter, NSX-T and HCX", + "guid": "71e68ce3-982e-5e56-0191-01100ad0e66f", + "link": "https://learn.microsoft.com/en-us/answers/questions/171195/how-to-create-jump-server-in-azure-not-bastion-paa.html", + "services": [ + "Bastion", + "AVS" + ], + "severity": "Medium", + "subcategory": "Jumpbox & Bastion", + "text": "Remote connectivity to AVS" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Name the jumpbox and identify the subnet where it will be hosted", + "guid": "6f8e93a2-44b1-bb1d-28a1-4d5b3c2ea857", + "link": "https://learn.microsoft.com/en-us/azure/bastion/tutorial-create-host-portal", + "services": [ + "VNet", + "Bastion", + "AVS" + ], + "severity": "Medium", + "subcategory": "Jumpbox & Bastion", + "text": "Configure a jumbox and Azure Bastion" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Provides secure / seamless RDP/SSH connectivity to your vm's directly through the portal.", + "guid": "ba430d58-4541-085c-3641-068c00be9bc5", + "link": "https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview", + "services": [ + "Bastion", + "VM", + "AVS" + ], + "severity": "Medium", + "subcategory": "Jumpbox & Bastion", + "text": "Security measure allowing RDP access via the portal" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Using a VPN to connect to Azure to enable VMware communications (HCX) (not recommended)", + "guid": "9988598f-2a9f-6b12-9b46-488415ceb325", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/configure-site-to-site-vpn-gateway", + "services": [ + "VPN", + "AVS" + ], + "severity": "Medium", + "subcategory": "VPN", + "text": "Connect to Azure using a VPN" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution 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", + "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": [ + "VPN", + "AVS" + ], + "severity": "Medium", + "subcategory": "VPN", + "text": "Bandwidth sizing" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "What traffic is routed through a firewall, what goes directly into Azure", + "guid": "e095116f-0bdc-4b51-4d71-b9e469d56f59", + "link": "https://learn.microsoft.com/en-us/azure/architecture/solution-ideas/articles/azure-vmware-solution-foundation-networking", + "services": [ + "VPN", + "AVS" + ], + "severity": "Medium", + "subcategory": "VPN", + "text": "Traffic routing " + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Name and unique address space for the vWAN, name for the vWAN hub", + "guid": "4dc480ac-cecd-39c4-fdc6-680b300716ab", + "link": "https://learn.microsoft.com/en-us/azure/virtual-wan/virtual-wan-site-to-site-portal#openvwan", + "services": [ + "VWAN", + "AVS" + ], + "severity": "Medium", + "subcategory": "vWAN hub", + "text": "vWAN name, hub name and address space" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Select either boh or the appropriate connection type.", + "guid": "51d6affd-8e02-6aea-d3d4-0baf618b3076", + "link": "https://learn.microsoft.com/en-us/azure/virtual-wan/virtual-wan-point-to-site-portal", + "services": [ + "VPN", + "AVS", + "VWAN" + ], + "severity": "Medium", + "subcategory": "vWAN hub", + "text": "ExR and/or VPN gateway provisioned" + }, + { + "category": "Connectivity", + "checklist": "Azure VMware Solution Checklist", + "description": "Add Azure firewall to vWAN (recommended)", + "guid": "e32a4c67-3dc0-c134-1c12-52d46dcbab5b", + "link": "https://learn.microsoft.com/en-us/azure/virtual-wan/virtual-wan-expressroute-portal", + "services": [ + "VWAN", + "Firewall", + "AVS" + ], + "severity": "Medium", + "subcategory": "vWAN hub", + "text": "Secure vWAN" }, { - "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", + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Active directory or other identity provider servers", + "guid": "fbc47fbf-bc96-fa93-ed5d-8c9be63cd5c3", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/configure-identity-source-vcenter", + "services": [ + "Entra", + "AVS" + ], "severity": "Medium", - "subcategory": "Vulnerability Management", - "text": "Deploy validated container images" + "subcategory": "Access", + "text": "External Identity (user accounts)" }, { - "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", - "severity": "High", - "subcategory": "Vulnerability Management", - "text": "Use up-to-date platforms, languages, protocols and frameworks" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Not required for LDAPS, required for Kerberos", + "guid": "b5db7975-f6bb-8ba3-ee5f-e3e805887997", + "link": "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", + "services": [ + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Access", + "text": "If using AD domain, ensure Sites & Services has been configured" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "785c2fa5-5b56-4ad4-a408-fe72734c476b", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/containers/aks/secure-baseline-aks", + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Authentication for users, must be secure.", + "guid": "c30749c4-e2af-558c-2eb9-0b6ae84881d1", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/configure-identity-source-vcenter", + "services": [ + "Entra", + "AVS" + ], "severity": "Medium", - "subcategory": "Development", - "text": "Use canary or blue/green deployments" + "subcategory": "Access", + "text": "Use LDAPS not ldap ( vCenter)" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "ab5351f6-383a-45ed-9c5e-b143b16db40a", - "link": "https://learn.microsoft.com/azure/aks/use-windows-hpc", - "severity": "Low", - "subcategory": "Development", - "text": "If required for AKS Windows workloads HostProcess containers can be used" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Authentication for users, must be secure.", + "guid": "64cb9b5c-9edd-787e-1dd8-2b2338e51635", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/configure-external-identity-source-nsx-t", + "services": [ + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Access", + "text": "Use LDAPS not ldap (NSX-T)" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "guid": "a280dcf5-90ce-465d-b8e1-3f9ccbd46926", - "link": "https://learn.microsoft.com/azure/azure-functions/functions-kubernetes-keda", - "scale": 1, - "severity": "Low", - "simple": -1, - "subcategory": "Development", - "text": "Use KEDA if running event-driven workloads" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "CN or SAN names, no wildcards, contains private key - CER or PFX", + "guid": "bec285ab-037e-d629-81d1-f61dac23cd4c", + "link": "https://youtu.be/4jvfbsrhnEs", + "services": [ + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security", + "text": "Security certificate installed on LDAPS servers " }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "guid": "26886d20-b66c-457b-a591-19bf8e8f5c58", - "link": "https://dapr.io/", - "severity": "Low", - "simple": 1, - "subcategory": "Development", - "text": "Use Dapr to ease microservice development" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Standard Azure Roles Based Access Controls", + "guid": "4ba394a2-3c33-104c-8e34-2dadaba9cc73", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity", + "services": [ + "RBAC", + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security", + "text": "RBAC applied to Azure roles" }, { - "category": "Application Deployment", - "checklist": "Azure AKS Review", - "guid": "3acbe04b-be20-49d3-afda-47778424d116", - "ha": 1, - "link": "https://learn.microsoft.com/azure/developer/terraform/create-k8s-cluster-with-tf-and-aks", + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Create roles in vCenter required to meet minimum viable access guidelines", + "guid": "b04ca129-83a9-3494-7512-347dd2d766db", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity#view-the-vcenter-server-privileges", + "services": [ + "RBAC", + "Entra", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Infrastructure as Code", - "text": "Use automation through ARM/TF to create your Azure resources" + "subcategory": "Security", + "text": "RBAC model in vCenter" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "36cb45e5-7960-4332-9bdf-8cc23318da61", - "ha": 1, - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", - "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Schedule and perform DR tests regularly" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)", + "guid": "8e477d2f-8004-3dd0-93d6-0aece9e1b2fb", + "link": "Best practice", + "services": [ + "RBAC", + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security", + "text": "CloudAdmin role usage" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "170265f4-bb46-4a39-9af7-f317284797b1", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "For roles managing the Azure VMware Solution resource in the Azure Portal (no standing permissions allowed)", + "guid": "00e0b729-f9be-f600-8c32-5ec0e8f2ed63", + "link": "https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-configure", + "services": [ + "RBAC", + "Entra", + "AVS" + ], "severity": "Medium", - "subcategory": "High Availability", - "text": "Use Azure Traffic Manager or Azure Front Door as a global load balancer for region failover" + "subcategory": "Security ", + "text": "Is Privileged Identity Management implemented" }, { - "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, - "link": "https://learn.microsoft.com/azure/aks/availability-zones", + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "For the Azure VMware Solution PIM roles", + "guid": "0842d45f-41a8-8274-1155-2f6ed554d315", + "link": "https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-configure", + "services": [ + "RBAC", + "Entra", + "AVS" + ], "severity": "Medium", - "subcategory": "High Availability", - "text": "Use Availability Zones if they are supported in your Azure region" + "subcategory": "Security ", + "text": "Is Privileged Identity Management audit reporting implemented" }, { - "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, - "link": "https://learn.microsoft.com/azure/aks/uptime-sla", - "severity": "High", - "subcategory": "High Availability", - "text": "Use the SLA-backed AKS offering" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Best practice, also see Monitoring/Alerts", + "guid": "915cbcd7-0640-eb7c-4162-9f33775de559", + "link": "Best practice", + "services": [ + "Monitor", + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security ", + "text": "Limit use of CloudAdmin account to emergency access only" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "c1288b3c-6a57-4cfc-9444-51e1a3d3453a", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", - "severity": "Low", - "simple": -1, - "subcategory": "High Availability", - "text": "Use Disruption Budgets in your pod and deployment definitions" + "category": "Identity", + "checklist": "Azure VMware Solution Checklist", + "description": "Operational procedure", + "guid": "7effa0c0-9172-e8e4-726a-67dbea8be40a", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/rotate-cloudadmin-credentials?tabs=azure-portal", + "services": [ + "Entra", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security ", + "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "3c763963-7a55-42d5-a15e-401955387e5c", - "ha": 1, - "link": "https://learn.microsoft.com/azure/container-registry/container-registry-geo-replication", - "severity": "High", - "subcategory": "High Availability", - "text": "If using a private registry, configure region replication to store images in multiple regions" + "category": "Management", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/azure-arc/vmware-vsphere/overview", + "services": [ + "Arc", + "VM", + "AVS" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "AVS VM Management (Azure Arc)" }, { - "category": "BC and DR", - "checklist": "Azure AKS Review", - "guid": "bc14aea6-e65d-48d9-a3ad-c218e6436b06", - "ha": 1, - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/business-continuity-and-disaster-recovery", - "severity": "High", - "subcategory": "Requirements", - "text": "Define non-functional requirements such as SLAs, RTO (Recovery Time Objective) and RPO (Recovery Point Objective)." + "category": "Management", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/governance/policy/overview", + "services": [ + "AzurePolicy", + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Azure policy" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "f82cb8eb-8c0a-4a63-a25a-4956eaa8dc4a", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/aks/eslz-cost-governance-with-kubecost", - "severity": "Low", - "subcategory": "Cost", - "text": "Use an external application such as kubecost to allocate costs to different users" + "category": "Management", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/lock-resources?tabs=json#configure-locks", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Resource locks" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "64d1a846-e28a-4b6b-9a33-22a635c15a21", - "link": "https://learn.microsoft.com/azure/aks/node-pool-snapshot", - "severity": "Low", - "subcategory": "Cost", - "text": "If required scale NodePool snapshots" + "category": "Management", + "checklist": "Azure VMware Solution Checklist", + "description": "For manual deployments, all configuration and deployments must be documented", + "guid": "8f2c46aa-ca1b-cad3-3ac9-213dfc0a265e", + "link": "Make sure to create your own runbook on the deployment of AVS.", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Run books" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "4d3dfbab-9924-4831-a68d-fdf0d72f462c", - "link": "https://learn.microsoft.com/azure/aks/scale-down-mode", - "severity": "Low", - "subcategory": "Cost", - "text": "Use scale down mode to delete/delallocate nodes" + "category": "Management", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations", + "services": [ + "AVS", + "AKV" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Naming conventions for auth keys" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "For automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "guid": "e22a2d99-eb71-7d7c-07af-6d4cdb1d4443", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "services": [ + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Alerts", + "text": "Create warning alerts for critical thresholds " + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "for automatic alerting on Azure VMware Solution performance (CPU >80%, Avg Memory >80%, vSAN >70%)", + "guid": "6d02f159-627d-79bf-a931-fab6d947eda2", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "services": [ + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Alerts", + "text": "Create critical alert vSAN consumption" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Provides platform alerts (generated by Microsoft)", + "guid": "1cc97b39-2c7e-246f-6d73-789cfebfe951", + "link": "https://www.virtualworkloads.com/2021/04/azure-vmware-solution-azure-service-health/", + "services": [ + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Alerts", + "text": "Configured for Azure Service Health alerts and notifications" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/set-up-backup-server-for-azure-vmware-solution", + "services": [ + "VM", + "AzurePolicy", + "AVS", + "Monitor", + "Backup" + ], + "severity": "Medium", + "subcategory": "Backup", + "text": "Backup policy" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Keep in mind the lead time for requesting new nodes", + "guid": "4ec7ccfb-795e-897e-4a84-fd31c04eadc6", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-alerts-for-azure-vmware-solution", + "services": [ + "AzurePolicy", + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Capacity", + "text": "Policy around ESXi host density and efficiency" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Azure Cost Management can be used - one option, put AVS in it's own Subscription. ", + "guid": "7f8f175d-13f4-5298-9e61-0bc7e9fcc279", + "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/govern", + "services": [ + "Cost", + "Monitor", + "Subscriptions", + "AVS" + ], + "severity": "Medium", + "subcategory": "Costs", + "text": "Ensure a good cost management process is in place for Azure VMware Solution - " + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Create dashboards to enable core Azure VMware Solution monitoring insights", + "guid": "01e689e0-7c6c-b58f-37bd-4d6b9b1b9c74", + "link": "https://docs.microsoft.com/en-us/azure/azure-portal/azure-portal-dashboards", + "services": [ + "Monitor", + "AVS", + "NetworkWatcher" + ], + "severity": "Medium", + "subcategory": "Dashboard", + "text": "Connection monitor dashboard" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-vmware-syslogs", + "services": [ + "Monitor", + "Storage", + "AVS" + ], + "severity": "Medium", + "subcategory": "Logs & Metrics", + "text": "Configure Azure VMware Solution logging " + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Must be on-premises, implement if available", + "guid": "7cbac8c3-4eda-d5d9-9bda-c6b5abba9fb6", + "link": "Is vROPS or vRealize Network Insight going to be used? ", + "services": [ + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Logs & Metrics", + "text": "vRealize Operations" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor", + "guid": "b243521a-644d-f865-7fb6-21f9019c0dd2", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-vmware-syslogs", + "services": [ + "Monitor", + "VM", + "AVS" + ], + "severity": "Medium", + "subcategory": "Logs & Metrics", + "text": "AVS VM logging" + }, + { + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Between on-premises to Azure are monitored using 'connection monitor'", + "guid": "2ca97d91-dd36-7229-b668-01036ccc3cd3", + "link": "https://learn.microsoft.com/en-us/azure/network-watcher/connection-monitor-create-using-portal", + "services": [ + "VPN", + "AVS", + "Monitor", + "NetworkWatcher", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Network", + "text": "Monitor ExpressRoute and/or VPN connections " }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "87e651ea-bc4a-4a87-a6df-c06a4b570ebc", - "link": "https://learn.microsoft.com/azure/aks/gpu-multi-instance", + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "To monitor the Azure VMware Solution back-end ExpressRoute connection (Azure native to AVS)", + "guid": "99209143-60fe-19f0-5633-8b5671277ba5", + "link": "https://learn.microsoft.com/en-us/azure/network-watcher/connection-monitor-create-using-portal", + "services": [ + "Monitor", + "ExpressRoute", + "AVS" + ], "severity": "Medium", - "subcategory": "Cost", - "text": "When required use multi-instance partioning GPU on AKS Clusters" + "subcategory": "Network", + "text": "Monitor from an Azure native resource to an Azure VMware Solution VM" }, { - "category": "Cost Governance", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "2b72a08b-0410-4cd6-9093-e068a5cf27e8", - "link": "https://learn.microsoft.com/azure/aks/start-stop-nodepools", - "severity": "Low", - "subcategory": "Cost", - "text": "If running a Dev/Test cluster use NodePool Start/Stop" + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "To monitor end-to-end, on-premises to AVS workloads", + "guid": "b9e5867c-57d3-036f-fb1b-3f0a71664efe", + "link": "https://learn.microsoft.com/en-us/azure/network-watcher/connection-monitor-create-using-portal", + "services": [ + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "Network", + "text": "Monitor from an on-premises resource to an Azure VMware Solution VM" }, { - "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", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Track requests to Azure VMware Solution and Azure VMware Solution based workloads", + "guid": "4af7c5f7-e5e9-bedf-a8cf-314b81735962", + "link": "Firewall logging and alerting rules are configured (Azure Firewall or 3rd party)", + "services": [ + "Monitor", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Use Azure Policy for Kubernetes to ensure cluster compliance" + "subcategory": "Security", + "text": "Auditing and logging is implemented for inbound internet " }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/use-system-pools", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "services": [ + "Monitor", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Separate applications from the control plane with user/system nodepools" + "subcategory": "Security", + "text": "Session monitoring " }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "a7a1f893-9bda-4477-98f2-4c116775c2ea", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/use-system-pools", - "severity": "Low", - "simple": -1, - "subcategory": "Compliance", - "text": "Add taint to your system nodepool to make it dedicated" + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Enable Diagnostic and metric logging on Azure VMware Solution", + "guid": "a434b3b5-f258-0845-cd76-d7df6ef5890e", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-vmware-syslogs", + "services": [ + "Monitor", + "AVS" + ], + "severity": "Medium", + "subcategory": "VMWare", + "text": "Logging and diagnostics" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "55b46a94-8008-4ae7-b7e4-b475b6c8bdbf", - "link": "https://learn.microsoft.com/azure/container-registry/", - "security": 1, + "category": "Monitoring", + "checklist": "Azure VMware Solution Checklist", + "description": "Monitor AVS workloads (each VM in AVS)", + "guid": "fb00b69a-83ec-ce72-446e-6c23a0cab09a", + "link": "https://docs.microsoft.com/en-us/azure/azure-monitor/agents/agent-windows?tabs=setup-wizard", + "services": [ + "Monitor", + "VM", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Use a private registry for your images, such as ACR" + "subcategory": "VMware", + "text": "Log Analytics Agents deployed on Azure VMware Solution guest VM workloads" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "59bce65d-e8a0-43f9-9879-468d66a786d6", - "link": "https://learn.microsoft.com/azure/security-center/container-security", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Checklist", + "description": "Decision on traffic flow", + "guid": "a1354b87-e18e-bf5c-c50b-8ddf0540e971", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-hub-and-spoke", + "services": [ + "AVS" + ], "severity": "Medium", - "subcategory": "Compliance", - "text": "Scan your images for vulnerabilities" + "subcategory": "Hub & Spoke", + "text": "North/South routing through Az Firewall or 3rd party " }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "cc639637-a652-42ac-89e8-06965388e9de", - "link": "https://learn.microsoft.com/azure/security-center/container-security", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-hub-and-spoke", + "services": [ + "AVS" + ], "severity": "Medium", - "subcategory": "Compliance", - "text": "Use Azure Security Center to detect security posture vulnerabilities" + "subcategory": "Hub & Spoke", + "text": "East West (Internal to Azure)" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "42d4aefe-2383-470e-b019-c30df24996b2", - "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#add-a-fips-enabled-node-pool", - "security": 1, - "severity": "Low", - "subcategory": "Compliance", - "text": "If required configure FIPS" + "category": "Networking", + "checklist": "Azure VMware Solution Checklist", + "description": "Requires a 3rd party NVA with Azure Route server - Scenario 2 (see link)", + "guid": "ebd3cc3c-ac3d-4293-950d-cecd8445a523", + "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "services": [ + "NVA", + "ARS", + "AVS" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "ExR without Global Reach" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "d167dd18-2b0a-4c24-8b99-9a646f8389a7", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-cluster-isolation", - "security": 1, - "severity": "High", - "subcategory": "Compliance", - "text": "Define app separation requirements (namespace/nodepool/cluster)" + "category": "Networking", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/route-server/route-server-faq", + "services": [ + "ARS", + "AVS" + ], + "severity": "Medium", + "subcategory": "Hub & Spoke", + "text": "Route server " }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "5e3df584-eccc-4d97-a3b6-bcda3b50eb2e", - "link": "https://github.com/Azure/secrets-store-csi-driver-provider-azure", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Checklist", + "description": "Via on-premises, Az Firewall, 3rd Party, NSX-T pubic IP", + "guid": "a4070dad-3def-818d-e9f7-be440d10e7de", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-design-public-internet-access", + "services": [ + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Secrets", - "text": "Store your secrets in Azure Key Vault with the CSI Secrets Store driver" + "subcategory": "Internet", + "text": "Egress point(s)" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "guid": "b03dda6d-58d7-4c89-8ddb-107d5769ae66", - "link": "https://learn.microsoft.com/azure/aks/update-credentials", - "security": 1, - "severity": "High", - "subcategory": "Secrets", - "text": "If using Service Principals for the cluster, refresh credentials periodically (like quarterly)" + "category": "Networking", + "checklist": "Azure VMware Solution Checklist", + "description": "Az Firewall, 3rd party NVA, Application Gateway, Azure Frontdoor ", + "guid": "e942c03d-beaa-3d9f-0526-9b26cd5e9937", + "link": "Research and choose optimal solution for each application", + "services": [ + "AppGW", + "FrontDoor", + "NVA", + "AVS" + ], + "severity": "Medium", + "subcategory": "Internet", + "text": "Internet facing applications" }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "e7ba73a3-0508-4f80-806f-527db30cee96", - "link": "https://learn.microsoft.com/azure/aks/use-kms-etcd-encryption", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/route-server/route-server-faq#route-server-limits", + "services": [ + "ARS", + "AVS" + ], "severity": "Medium", - "subcategory": "Secrets", - "text": "If required add Key Management Service etcd encryption" + "subcategory": "Routing", + "text": "When route server Route limit understood? " }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "ec8e4e42-0344-41b0-b865-9123e8956d31", - "link": "https://learn.microsoft.com/azure/confidential-computing/confidential-nodes-aks-overview", - "security": 1, - "severity": "Low", - "subcategory": "Secrets", - "text": "If required consider using Confidential Compute for AKS" + "category": "Networking", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/ddos-protection/manage-ddos-protection", + "services": [ + "VM", + "FrontDoor", + "VPN", + "AVS", + "AppGW", + "DDoS", + "VNet", + "ExpressRoute", + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": "Security", + "text": "Is DDoS standard protection of public facing IP addresses? " }, { - "category": "Governance and Security", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "c9e95ffe-6dd1-4a17-8c5f-110389ca9b21", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-enable", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution Checklist", + "description": "To manage Azure VMware Solution, vCenter, NSX manager and HCX manager", + "guid": "d43da920-4ecc-a4e9-dd45-a2986ce81d32", + "link": "Best practice: Bastion or 3rd party tool", + "services": [ + "AVS" + ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Consider using Defender for Containers" + "subcategory": "Security", + "text": "Use a dedicated privileged access workstation (PAW)" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/use-managed-identity", - "severity": "High", - "simple": 1, - "subcategory": "Identity", - "text": "Use managed identities instead of Service Principals" + "category": "Networking", + "checklist": "Azure VMware Solution Checklist", + "description": "Use NSX-T for inter-vmware-traffic inspection", + "guid": "a2dac74f-5380-6e39-25e6-f13b99ece51f", + "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-F6685367-7AA1-4771-927E-ED77727CFDA3.html", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Traffic Inspection", + "text": "East West (Internal to AVS)" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/managed-aad", + "category": "Networking", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/architecture/networking/hub-spoke-vwan-architecture", + "services": [ + "VWAN", + "Firewall", + "AVS" + ], "severity": "Medium", - "simple": 1, - "subcategory": "Identity", - "text": "Integrate authentication with AAD (using the managed integration)" + "subcategory": "vWAN", + "text": "Use Secure Hub (Azure Firewall or 3rd party)" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "a2fe27b2-e287-401a-8352-beedf79b488d", - "link": "https://learn.microsoft.com/azure/aks/control-kubeconfig-access", - "security": 1, + "category": "Networking", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/firewall-manager/secure-cloud-network", + "services": [ + "VWAN", + "AVS" + ], + "severity": "Medium", + "subcategory": "vWAN", + "text": "East West (Internal to Azure)" + }, + { + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/configure-nsx-network-components-azure-portal", + "services": [ + "Subscriptions", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "Limit access to admin kubeconfig (get-credentials --admin)" + "subcategory": "Automated Scale", + "text": "Scale out operations planning" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "eec4962c-c3bd-421b-b77f-26e5e6b3bec3", - "link": "https://learn.microsoft.com/azure/aks/manage-azure-rbac", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", + "services": [ + "AzurePolicy", + "Storage", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "Integrate authorization with AAD RBAC" + "subcategory": "Automated Scale", + "text": "Scale in operations planning" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "d4f3537c-1346-4dc5-9027-a71ffe1bd05d", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-identity", - "security": 1, - "severity": "High", - "simple": -1, - "subcategory": "Identity", - "text": "Use namespaces for restricting RBAC privilege in Kubernetes" + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-platform-automation-and-devops#automated-scale", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Automated Scale", + "text": "Scale serialized operations planning" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "d2e0d5d7-71d4-41e3-910c-c57b4a4b1410", - "link": "https://learn.microsoft.com/azure/aks/workload-identity-migration-sidecar", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Checklist", + "description": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)", + "guid": "68161d66-5707-319b-e77d-9217da892593", + "link": "Best practice (testing)", + "services": [ + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "For POD Identity Access Management use Azure AD Workload Identity (preview)" + "subcategory": "Automated Scale", + "text": "Scale rd operations planning" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "f4dcf690-1b30-407d-abab-6f8aa780d3a3", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#non-interactive-sign-in-with-kubelogin", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Checklist", + "description": "Define and enforce scale in/out maximum limits for your environment in the automations", + "guid": "c32cb953-e860-f204-957a-c79d61202669", + "link": "Operational planning - understand workload requirements", + "services": [ + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "For AKS non-interactive logins use kubelogin (preview)" + "subcategory": "Automated Scale", + "text": "Scale maximum operations planning" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts", - "security": 1, + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution 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", + "link": "https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-management-and-monitoring", + "services": [ + "Monitor", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "Disable AKS local accounts" + "subcategory": "Automated Scale", + "text": "Monitor scaling operations " }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "36abb0db-c118-4f4c-9880-3f30f9a2deb6", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#configure-just-in-time-cluster-access-with-azure-ad-and-aks", - "security": 1, - "severity": "Low", - "simple": -1, - "subcategory": "Identity", - "text": "Configure if required Just-in-time cluster access" + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution Checklist", + "description": "Consider the use of Azure Private-Link when using other Azure Native Services", + "guid": "95e374af-8a2a-2672-7ab7-b4a1be43ada7", + "link": "https://learn.microsoft.com/en-us/azure/private-link/private-link-overview", + "services": [ + "PrivateLink", + "AVS" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Private link" }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "c4d7f4c6-79bf-45d0-aa05-ce8fc717e150", - "link": "https://learn.microsoft.com/azure/aks/managed-aad#use-conditional-access-with-azure-ad-and-aks", - "security": 1, - "severity": "Low", - "simple": -1, - "subcategory": "Identity", - "text": "Configure if required AAD conditional access for AKS" + "category": "Other Services/Operations", + "checklist": "Azure VMware Solution 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", + "link": "Best practice", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Provisioning Vmware VLANs" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "In which region will AVS be deployed", + "guid": "04e3a2f9-83b7-968a-1044-2811811a924b", + "link": "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/understanding-active-directory-site-topology", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Region selected" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Are there regulatory or compliance policies in play", + "guid": "e52d1615-9cc6-565c-deb6-743ed7e90f4b", + "link": "Internal policy or regulatory compliance", + "services": [ + "AzurePolicy", + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Data residency compliant with selected regions" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Request through the support blade", + "guid": "92bd5ad6-441f-a983-7aa9-05dd669d760b", + "link": "https://learn.microsoft.com/en-us/azure/migrate/concepts-azure-vmware-solution-assessment-calculation", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Request for number of AVS hosts submitted " + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "PG approval for deployment", + "guid": "28370f63-1cb8-2e35-907f-c5516b6954fa", + "link": "Support request through portal or get help from Account Team", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Region and number of AVS nodes approved" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Portal/subscription/resource providers/ Microsoft.AVS", + "guid": "96c76997-30a6-bb92-024d-f4f93f5f57fa", + "link": "Done through the subscription/resource providers/ AVS register in the portal", + "services": [ + "Subscriptions", + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Resource provider for AVS registered" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Connectivity, subscription & governanace model", + "guid": "5898e3ff-5e6b-bee1-6f85-22fee261ce63", + "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/enterprise-scale-landing-zone", + "services": [ + "Subscriptions", + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Landing zone architecture" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "The name of the RG where AVS will exist", + "guid": "d0181fb8-9cb8-bf4b-f5e5-b5f9bf7ae4ea", + "link": "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Resource group name selected" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Each resource created as part of the deployment will also utilize this prefix in the name", + "guid": "0f0d20c2-5a19-726c-de20-0984e070d9d6", + "link": "Best practice - naming standards", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Deployment prefix selected" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "/22 unique non-overlapping IPv4 address space", + "guid": "7fbf2ab7-a36c-5957-c27a-67038557af2a", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/tutorial-network-checklist#routing-and-subnet-considerations", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Network space for AVS management layer" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "vNets used by workloads running in AVS (non-stretched)", + "guid": "0c87f999-e517-21ef-f355-f210ad4134d2", + "link": "https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/installation/GUID-4B3860B8-1883-48CA-B2F3-7C2205D91D6D.html", + "services": [ + "VNet", + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Network space for AVS NSX-T segments" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Choose AV36, AV36P, AV52, AV36T (AV36T = Trial)", + "guid": "946c8966-f902-6f53-4f37-00847e8895c2", + "link": "https://azure.microsoft.com/en-us/pricing/details/azure-vmware/", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "AVS SKU (region dependent)" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/migrate/how-to-assess", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Number of hosts to be deployed" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Understand how and if you should be using reserved instances (cost control)", + "guid": "f2b73c4f-3d46-32c9-5df1-5b8dfcd3947f", + "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": [ + "Cost", + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Reserverd Instances" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement", + "guid": "94ac48ab-ade5-3fa7-f800-263feeb97070", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "services": [ + "ASR", + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Capacity " + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution Checklist", + "description": "Identify which of the networking scenarios make ", + "guid": "1f9d4bd5-14b8-928c-b4cb-eb211f9b8de5", + "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/azure-vmware/eslz-network-topology-connectivity", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "Networking & Connectivity See docs describing scenrario 1 through 5" + }, + { + "category": "Planning", + "checklist": "Azure VMware Solution 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", + "link": "Please Check Partner Ecosystem", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Pre-deployment", + "text": "3rd party application compatibility " }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "e1123a7c-a333-4eb4-a120-4ee3f293c9f3", - "link": "https://learn.microsoft.com/azure/aks/use-group-managed-service-accounts", - "security": 1, - "severity": "Low", - "simple": -1, - "subcategory": "Identity", - "text": "If required for Windows AKS workloads configure gMSA " + "category": "Security", + "checklist": "Azure VMware Solution Checklist", + "description": "MS Defender For Cloud, for workloads running on Azure VMware Solution", + "guid": "f42b0b09-c591-238a-1580-2de3c485ebd2", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/azure-security-integration#prerequisites", + "services": [ + "Defender", + "AVS" + ], + "severity": "Medium", + "subcategory": "Security", + "text": "Enable Advanced Threat Detection " }, { - "category": "Identity and Access Management", - "checklist": "Azure AKS Review", - "guid": "1f711a74-3672-470b-b8b8-a2148d640d79", - "link": "https://learn.microsoft.com/azure/aks/use-managed-identity#use-a-pre-created-kubelet-managed-identity", - "security": 1, + "category": "Security", + "checklist": "Azure VMware Solution Checklist", + "description": "Are the applicable policies enabled (compliance baselines added to MDfC)", + "guid": "bcdd2348-3d0e-c6bb-1092-aa4cd1a66d6b", + "link": "https://docs.microsoft.com/en-us/azure/azure-vmware/azure-security-integration", + "services": [ + "AzurePolicy", + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Identity", - "text": "For finer control consider using a managed Kubelet Identity" + "subcategory": "Security", + "text": "Policy & Regulatory Compliance" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "cbd8ac2a-aebc-4a2a-94da-1dbf3dc99248", - "link": "https://azure.github.io/application-gateway-kubernetes-ingress/setup/install-existing/", - "security": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Azure to Azure (E/W), Azure to On-premises), AVS to Internet, AVS to Azure", + "guid": "607c1ca9-da92-ae19-5a4c-eb1e876acbe7", + "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": [ + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Best practices", - "text": "If using AGIC, do not share an AppGW across clusters" + "subcategory": "Firewalls", + "text": "Azure / 3rd party firewall" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/http-application-routing", - "scale": 1, - "severity": "High", - "simple": -1, - "subcategory": "Best practices", - "text": "Do not use AKS Application Routing Add-On" + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "To allow HCX appliance to connect/sync", + "guid": "1d87925c-c02b-7fde-a425-7e95ad846a27", + "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": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Firewalls", + "text": "Firewalls allow for East/West traffic inside AVS" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", - "scale": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Decision on which tool to use (SRM requires additional license - enables automation & other features)", + "guid": "468b3495-2f6e-b65a-38ef-3ba631bcaa46", + "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-B842696B-89EF-4183-9C73-B77157F56055.html", + "services": [ + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Best practices", - "text": "For Windows workloads use Accelerated Networking" + "subcategory": "Networking", + "text": "HCX and/or SRM" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", - "scale": 1, - "severity": "High", - "subcategory": "Best practices", - "text": "Use the standard ALB (as opposed to the basic one)" + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Read up on requirements for Service Mesh requirements and how HCX ", + "guid": "be2ced52-da08-d366-cf7c-044c19e29509", + "link": "https://docs.vmware.com/en/VMware-HCX/4.6/hcx-user-guide/GUID-76BCD059-A31A-4041-9105-ACFB56213E7C.html", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Configuring and Managing the HCX Interconnect" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "22fbe8d6-9b40-47ef-9011-25bb1a555a6b", - "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#add-a-node-pool-with-a-unique-subnet", - "security": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "If you are planning on using stretch networks ensure that your on-premises environment requirements", + "guid": "7dcac579-fc5c-5c9c-f1f7-9b1149ff2c37", + "link": "https://docs.vmware.com/en/VMware-HCX/4.2/hcx-user-guide/GUID-DBDB4D1B-60B6-4D16-936B-4AC632606909.html", + "services": [ + "AVS" + ], "severity": "Medium", - "simple": -2, - "subcategory": "Best practices", - "text": "If using Azure CNI, consider using different Subnets for NodePools" + "subcategory": "Networking", + "text": "Restrictions and limitations for network extensions" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "c3c39c98-6bb2-4c12-859a-114b5e3df584", - "link": "https://learn.microsoft.com/azure/private-link/private-link-overview", - "security": 1, + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Do workloads require MoN?", + "guid": "cf45c0b9-6c4b-3bfb-86c5-62fe54061c73", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/vmware-hcx-mon-guidance", + "services": [ + "AVS" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Cost", - "text": "Use Private Endpoints (preferred) or Virtual Network Service Endpoints to access PaaS services from the cluster" + "subcategory": "Networking", + "text": "Mobility optimized networking" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Operating system level of Vmware environment", + "guid": "b7cf11f3-b12e-5189-991a-06df5250d2ca", + "link": "https://learn.microsoft.com/en-us/azure/site-recovery/vmware-physical-azure-support-matrix", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Support matrix (OS versions etc)." + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Required that all switches are dynamic", + "guid": "45fe9252-aa1b-4e30-45c6-bc02f3b76acf", + "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": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Standard switches converted to dynamic switches" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "See sections on sizing and capacity in the link.", + "guid": "e9f6d736-ee44-e2ac-e7f9-e361f8c857f3", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/plan-private-cloud-deployment", + "services": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Capacity for HCX appliance" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Check hardware restrictions to ensure compatibility with AVS/OS ", + "guid": "1be2cdd6-15a7-9a33-aea7-113859035ce9", + "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": [ + "AVS" + ], + "severity": "Medium", + "subcategory": "On-premises pre-requisites", + "text": "Hardware compatibility" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Need to be converted", + "guid": "16ab821a-27c6-b6d3-6042-10dc4d6dfcb7", + "link": "https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.storage.doc/GUID-01D3CF47-A84A-4988-8103-A0487D6441AA.html", + "services": [ + "Storage", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "VSAN RDM disks are converted - not supported." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "e8a03f97-8794-468d-96a7-86d60f96c97b", - "ha": 1, - "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering", + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Need to be converted", + "guid": "eb2f9313-afb2-ab35-aa24-6d97a3cb0611", + "link": "3rd-Party tools", + "services": [ + "Storage", + "VM", + "AVS" + ], "severity": "Medium", - "subcategory": "HA", - "text": "If hybrid connectivity is required, use 2xER or ER+VPN for better availability" + "subcategory": "Storage", + "text": "VM with SCSI shared bus are not supported" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", - "severity": "High", - "simple": 1, - "subcategory": "IPAM", - "text": "Choose the best CNI network plugin for your requirements (Azure CNI recommended)" + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Remove Direct IO before migration", + "guid": "3f2a5cff-c8a6-634a-1f1b-53ef9d321381", + "link": "Contact VMware", + "services": [ + "Storage", + "VM", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "VM with Direct IO require removing DirectPath device" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "7faf12e7-0943-4f63-8472-2da29c2b1cd6", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", - "scale": 1, - "severity": "High", - "subcategory": "IPAM", - "text": "If using Azure CNI, size your subnet accordingly considering the maximum number of pods per node" + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Cannot migrate clusters ", + "guid": "efc8a311-74f8-0252-c6a0-4bac7610e266", + "link": "Contact VMware", + "services": [ + "Storage", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Shared VMDK files are not supported" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "22f54b29-bade-43aa-b1e8-c38ec9366673", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", - "scale": 1, - "severity": "High", - "simple": -1, - "subcategory": "IPAM", - "text": "If using Azure CNI, check the maximum pods/node (default 30)" + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Convert to a different format", + "guid": "ab6c89cd-a26f-b894-fe59-61863975458e", + "link": "Contact VMware", + "services": [ + "Storage", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "RDM with 'physical compatibility mode' are not supported." }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/internal-lb", - "security": 1, + "category": "VMware", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "services": [ + "AzurePolicy", + "Storage", + "VM", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Default storage policy" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution 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", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/configure-storage-policy", + "services": [ + "AzurePolicy", + "Storage", + "VM", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Ensure that the appropriate VM template storage policy is used" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs", + "guid": "ebebd109-9f9d-d85e-1b2f-d302012843b7", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-storage#storage-policies-and-fault-tolerance", + "services": [ + "AzurePolicy", + "Storage", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Failure to tolerate policy" + }, + { + "category": "VMware", + "checklist": "Azure VMware Solution Checklist", + "description": "ANF can be used to extend storage for Azure VMware Solution,", + "guid": "1be821bd-4f37-216a-3e3d-2a5ac6996863", + "link": "https://learn.microsoft.com/en-us/azure/azure-vmware/netapp-files-with-azure-vmware-solution", + "services": [ + "Storage", + "AVS" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Use ANF for external storage" + }, + { + "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", - "simple": -1, - "subcategory": "IPAM", - "text": "If using private-IP LoadBalancer services, use a dedicated subnet (not the AKS subnet)" + "subcategory": "VM Scale Sets", + "text": "Enable automatic instance repairs for enhanced VM Scale Sets resiliency", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", - "scale": 1, + "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": [ + "Backup", + "VM" + ], "severity": "High", - "subcategory": "IPAM", - "text": "Size the service IP address range accordingly (it is going to limit the cluster scalability)" + "subcategory": "Virtual Machines", + "text": "Consider Azure Backup to meet your resiliency requirements for Azure VMs", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "57bf217f-6dc8-481c-81e2-785773e9c00f", - "link": "https://learn.microsoft.com/azure/aks/use-byo-cni", - "security": 1, - "severity": "Low", - "simple": -2, - "subcategory": "Operations", - "text": "If required add your own CNI plugin" + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Virtual Machines", + "text": "Use Premium or Ultra disks for production VMs", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "4b3bb365-9458-44d9-9ed1-5c8f52890364", - "link": "https://learn.microsoft.com/azure/aks/use-multiple-node-pools#assign-a-public-ip-per-node-for-your-node-pools", - "security": 1, - "severity": "Low", - "simple": -2, - "subcategory": "Operations", - "text": "If required configure Public IP per node in AKS" + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Virtual Machines", + "text": "Ensure Managed Disks are used for all VMs", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "b3808b9f-a1cf-4204-ad01-3a923ce474db", - "link": "https://learn.microsoft.com/azure/aks/concepts-network", - "scale": 1, + "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": [ + "Storage", + "SQL", + "VM" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Scalability", - "text": "Use an ingress controller to expose web-based apps instead of exposing them with LoadBalancer-type services" + "subcategory": "Virtual Machines", + "text": "Do not use the Temp disk for anything that is not acceptable to be lost", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "ccb534e7-416e-4a1d-8e93-533b53199085", - "link": "https://learn.microsoft.com/azure/aks/nat-gateway", - "scale": 1, - "severity": "Low", - "simple": -1, - "subcategory": "Scalability", - "text": "Use Azue NAT Gateway as outboundType for scaling egress traffic" + "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": [ + "ACR", + "Storage", + "VM" + ], + "severity": "Medium", + "subcategory": "Virtual Machines", + "text": "Leverage Availability Zones for your VMs in regions where they are supported", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "8ee9a69a-1b58-4b1e-9c61-476e110a160b", - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni#dynamic-allocation-of-ips-and-enhanced-subnet-support", - "scale": 1, + "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": [ + "VM" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Scalability", - "text": "Use Dynamic allocations of IPs in order to avoid Azure CNI IP exhaustion" + "subcategory": "Virtual Machines", + "text": "For regions that do not support Availability Zones deploy VMs into Availability Sets", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/limit-egress-traffic", - "security": 2, + "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": [ + "ASR", + "VM" + ], "severity": "High", - "simple": -2, - "subcategory": "Security", - "text": "Filter egress traffic with AzFW/NVA if your security requirements mandate it" + "subcategory": "Virtual Machines", + "text": "Avoid running a production workload on a single VM", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges", - "security": 1, - "severity": "Medium", - "simple": -1, - "subcategory": "Security", - "text": "If using a public API endpoint, restrict the IP addresses that can access it" + "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": [ + "ASR", + "VM", + "AVS" + ], + "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": "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", - "link": "https://learn.microsoft.com/azure/aks/private-clusters", - "security": 1, - "severity": "High", - "simple": -1, - "subcategory": "Security", - "text": "Use private clusters if your requirements mandate it" + "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": [ + "VM" + ], + "severity": "Low", + "subcategory": "Virtual Machines", + "text": "Use Capacity Reservations for critical workloads that require guaranteed capacity", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/use-network-policies", - "security": 1, + "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": [ + "ASR", + "VM" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Security", - "text": "For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used " + "subcategory": "Virtual Machines", + "text": "Increase quotas in DR region before testing failover with ASR", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/use-network-policies", - "security": 1, - "severity": "High", - "subcategory": "Security", - "text": "Enable a Kubernetes Network Policy option (Calico/Azure)" + "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": [ + "VM" + ], + "severity": "Low", + "subcategory": "Virtual Machines", + "text": "Utilize Scheduled Events to prepare for VM maintenance", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "85e2223e-ce8b-4b12-907c-a5f16f158e3e", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", - "security": 1, - "severity": "High", - "simple": -1, - "subcategory": "Security", - "text": "Use Kubernetes network policies to increase intra-cluster security" + "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": [ + "Storage" + ], + "severity": "Medium", + "subcategory": "Storage Accounts", + "text": "Choose the most appropriate data redundancy option for Azure Storage based on your requirements", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "a3a92c2d-e7e2-4165-a3a8-7af4a7a1f893", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-network", - "security": 2, - "severity": "High", - "simple": -1, - "subcategory": "Security", - "text": "Use a WAF for web workloads (UIs or APIs)" + "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": [ + "Storage" + ], + "severity": "Low", + "subcategory": "Storage Accounts", + "text": "Apply a Delete lock to prevent accidental or malicious deletion of storage accounts", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-network/ddos-protection-overview", - "security": 2, - "severity": "Medium", - "subcategory": "Security", - "text": "Use DDoS Standard in the AKS Virtual Network" + "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": [ + "Storage" + ], + "severity": "Low", + "subcategory": "Storage Accounts", + "text": "Enable soft delete for Storage Account Containers", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/http-proxy", - "security": 2, + "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" + ], "severity": "Low", - "subcategory": "Security", - "text": "If required add company HTTP Proxy" + "subcategory": "Storage Accounts", + "text": "Enable soft delete for blobs", + "waf": "Reliability" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure AKS Review", - "guid": "e9855d04-c3c3-49c9-a6bb-2c12159a114b", - "link": "https://learn.microsoft.com/azure/aks/servicemesh-about", - "security": 1, + "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", - "simple": -2, - "subcategory": "Security", - "text": "Consider using a service mesh for advanced microservice communication management" + "subcategory": "Backup", + "text": "Enable Azure Backup enhanced soft delete for improved data protection and recovery", + "waf": "Reliability" + }, + { + "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": [ + "Backup" + ], + "severity": "Low", + "subcategory": "Backup", + "text": "Implement multi-user authorization for Azure Backup to ensure secure and controlled access to backup resources", + "waf": "Reliability" + }, + { + "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": [ + "Storage", + "Backup" + ], + "severity": "Low", + "subcategory": "Backup", + "text": "Implement Immutable Storage for your vaults to protect against ransomware and prevent unauthorized modifications to backups", + "waf": "Reliability" + }, + { + "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": [ + "ASR" + ], + "severity": "High", + "subcategory": "Design", + "text": "Define business continuity and disaster recovery requirements", + "waf": "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", + "RBAC" + ], + "severity": "Medium", + "subcategory": "DevOps", + "text": "Implement Infrastructure as Code (IaC) for Rapid Infrastructure Recovery", + "waf": "Reliability" + }, + { + "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": [ + "ASR" + ], + "severity": "Medium", + "subcategory": "Multi-region", + "text": "Plan for cross-region recovery by leveraging region pairs", + "waf": "Reliability" + }, + { + "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": [ + "AppGW" + ], + "severity": "Medium", + "subcategory": "Application Gateways", + "text": "Deploy Application Gateways with a minimum instance count of 2 to avoid instance provisioning downtime", + "waf": "Reliability" + }, + { + "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": [ + "AppGW", + "Storage" + ], + "severity": "High", + "subcategory": "Application Gateways", + "text": "Deploy Azure Application Gateway v2 for zone redundancy support", + "waf": "Reliability" + }, + { + "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": [ + "FrontDoor" + ], + "severity": "Low", + "subcategory": "Azure Front Door", + "text": "Consider a redundant traffic management solution in conjunction with Azure Front Door", + "waf": "Reliability" + }, + { + "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": [ + "ASR", + "TrafficManager", + "Monitor", + "DNS" + ], + "severity": "Low", + "subcategory": "DNS", + "text": "Plan for automated failover using Traffic Manager for DNS Traffic", + "waf": "Reliability" + }, + { + "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": [ + "ACR", + "ASR", + "DNS" + ], + "severity": "Low", + "subcategory": "DNS", + "text": "Implement DNS Failover using Azure DNS Private Resolvers", + "waf": "Reliability" + }, + { + "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": [ + "ACR" + ], + "severity": "Medium", + "subcategory": "Data Gateways", + "text": "Use on-premises data gateway clusters to ensure high availability for business-critical data", + "waf": "Reliability" + }, + { + "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": [ + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "ExpressRoute", + "text": "Ensure redundancy within both the partner network and customer network when utilizing ExpressRoute for high availability", + "waf": "Reliability" + }, + { + "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": "ExpressRoute", + "text": "When using multiple ExpressRoute circuits ensure that routing allows for a primary and backup", + "waf": "Reliability" + }, + { + "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": [ + "Cost", + "VPN", + "Backup", + "ExpressRoute" + ], + "severity": "Low", + "subcategory": "ExpressRoute", + "text": "Consider deploying site-to-site VPN as a backup for your ExpressRoute private peering", + "waf": "Reliability" + }, + { + "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": [ + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": "Load Balancers", + "text": "Leverage the Standard SKU for Load Balancers that handle traffic to production applications", + "waf": "Reliability" + }, + { + "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": [ + "VM", + "LoadBalancer" + ], + "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", + "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": [ + "Monitor", + "LoadBalancer" + ], + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "67f7a9ed-5b31-4f38-a3f3-9812b2463cff", - "ha": 1, - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-metric-alerts", + "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": [ + "NVA" + ], "severity": "High", - "simple": -1, - "subcategory": "Alerting", - "text": "Configure alerts on the most critical metrics (see Container Insights for recommendations)" + "subcategory": "NVAs", + "text": "Deploy Network Virtual Appliances (NVAs) in a vendor supported configuration for High Availability", + "waf": "Reliability" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "337453a3-cc63-4963-9a65-22ac19e80696", - "ha": 1, - "link": "https://learn.microsoft.com/azure/advisor/advisor-get-started", - "severity": "Low", - "simple": -1, - "subcategory": "Compliance", - "text": "Check regularly Azure Advisor for recommendations on your cluster" + "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": [ + "ACR", + "VPN" + ], + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "5388e9de-d167-4dd1-a2b0-ac241b999a64", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", - "severity": "Low", - "simple": 1, - "subcategory": "Compliance", - "text": "Develop your YAML manifests with intelligent text editors such as vscode+kubeadvisor" + "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": [ + "VPN" + ], + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "3aa70560-e7e7-4968-be3d-628af35b2ced", - "link": "https://learn.microsoft.com/azure/aks/certificate-rotation", - "severity": "Low", - "simple": 1, - "subcategory": "Compliance", - "text": "Enable AKS auto-certificate rotation" + "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": [ + "ASR" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Do not combine ASCS and Database cluster on to single/same VM" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "e189c599-df0d-45a7-9dd4-ce32c1881370", - "link": "https://learn.microsoft.com/azure/aks/supported-kubernetes-versions", - "security": 1, - "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" + "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": [ + "ASR", + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Make sure the Floating IP is enabled on the Load balancer" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "6f7c4c0d-4e51-4464-ad24-57ed67138b82", - "link": "https://learn.microsoft.com/azure/aks/node-updates-kured", - "severity": "High", - "simple": -1, - "subcategory": "Compliance", - "text": "Use kured for Linux node upgrades in case you are not using node-image upgrade" + "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": [ + "ASR", + "RBAC", + "Entra", + "VM" + ], + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "139c9580-ade3-426a-ba09-cf157d9f6477", - "link": "https://learn.microsoft.com/azure/aks/node-image-upgrade", - "security": 1, - "severity": "High", - "simple": -1, - "subcategory": "Compliance", - "text": "Have a regular process to upgrade the cluster node images periodically (weekly, for example)" + "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": [ + "ACR", + "ASR", + "SAP" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Use one proximity placement group per SAP SID. Groups don't span across Availability Zones or Azure regions" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "0102ce16-ee30-41e6-b882-e52e4621dd68", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/bedrock/bedrock-automated-deployments", - "severity": "Low", - "subcategory": "Compliance", - "text": "Consider gitops to deploy applications or cluster configuration to multiple clusters" + "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": [ + "ASR", + "Entra", + "VM" + ], + "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." }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "d7672c26-7602-4482-85a4-14527fbe855c", - "link": "https://learn.microsoft.com/azure/aks/command-invoke", - "severity": "Low", - "subcategory": "Compliance", - "text": "Consider using AKS command invoke on private clusters" + "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": [ + "ASR", + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Use a Standard Load Balancer SKU in front of ASCS and DB clusters" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "31d7aaab-7571-4449-ab80-53d89e89d17b", - "link": "https://learn.microsoft.com/azure/aks/node-auto-repair#node-autodrain", - "security": 1, - "severity": "Low", - "subcategory": "Compliance", - "text": "For planned events consider using Node Auto Drain" + "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": [ + "ASR", + "Storage", + "VM" + ], + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "ed0fda7f-211b-47c7-8b6e-c18873fb473c", - "link": "https://learn.microsoft.com/azure/aks/faq", - "security": 1, - "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')" + "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": [ + "ASR" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Native database replication technology should be used to synchronize the database in a HA pair." }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/cluster-configuration", - "severity": "Low", - "simple": 1, - "subcategory": "Compliance", - "text": "Use custom Node RG (aka 'Infra RG') name" + "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": [ + "ASR", + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "b2463cff-e189-4c59-adf0-d5a73dd4ce32", - "ha": 1, - "link": "https://kubernetes.io/docs/setup/release/notes/", + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "81b12318-1a54-4174-8583-3fb4ae3c2df7", + "services": [ + "VNet", + "ASR" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Compliance", - "text": "Do not use deprecated Kubernetes APIs in your YAML manifests" + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "c1881370-6f7c-44c0-b4e5-14648d2457ed", - "ha": 1, - "link": "https://learn.microsoft.com/azure-stack/aks-hci/adapt-apps-mixed-os-clusters", - "severity": "Low", - "simple": -1, - "subcategory": "Compliance", - "text": "Taint Windows nodes" + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "43165c3a-cbe0-45bb-b209-d490da477784", + "services": [ + "ASR", + "Entra", + "VM" + ], + "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)." }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "67138b82-0102-4ce1-9ee3-01e6e882e52e", - "link": "https://learn.microsoft.com/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-20H2%2Cwindows-10-20H2", - "severity": "Low", - "subcategory": "Compliance", - "text": "Keep windows containers patch level in sync with host patch level" + "category": "Business Continuity and Disaster Recovery", + "checklist": "Azure Landing Zone Review", + "guid": "24d11678-5d2f-4a56-a56a-d48408fe7273", + "services": [ + "ASR" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Native database replication should be used to synchronize data to the DR site, rather than Azure Site Recovery" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "description": "Via Diagnostic Settings at the cluster level", - "guid": "5b56ad48-408f-4e72-934c-476ba280dcf5", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/monitor-aks", - "severity": "Low", - "subcategory": "Compliance", - "text": "Send master logs (aka API logs) to Azure Monitor or your preferred log management solution" + "category": "Compute", + "checklist": "Azure Landing Zone Review", + "guid": "2829e2ed-b217-4367-9aff-6691b4935ada", + "services": [ + "VM" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Make quota requests for correct VM SKU and Zones" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "c5a5b252-1e44-4a59-a9d2-399c4d7b68d0", - "link": "https://learn.microsoft.com/azure/aks/spot-node-pool", - "severity": "Low", - "simple": -1, - "subcategory": "Cost", - "text": "Consider spot node pools for non time-sensitive workloads" + "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": [ + "Subscriptions", + "RBAC", + "Entra" + ], + "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/" }, { - "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", - "link": "https://learn.microsoft.com/azure/aks/concepts-scale", - "scale": 1, - "severity": "Low", - "simple": -1, - "subcategory": "Cost", - "text": "Consider AKS virtual node for quick bursting" + "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": [ + "SAP", + "Entra" + ], + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "6f8389a7-f82c-4b8e-a8c0-aa63a25a4956", - "ha": 1, - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", - "severity": "High", - "simple": -1, - "subcategory": "Monitoring", - "text": "Monitor your cluster metrics with Container Insights (or other tools like Prometheus)" + "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": [ + "SAP", + "Entra" + ], + "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." }, { - "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, - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview", - "severity": "High", - "simple": -1, - "subcategory": "Monitoring", - "text": "Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch)" + "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": [ + "SAP", + "Entra" + ], + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "4621dd68-c5a5-4be2-bdb1-1726769ef669", - "ha": 1, - "link": "https://learn.microsoft.com/azure/azure-monitor/containers/container-insights-analyze", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "9eb54dad-7861-4e1c-973a-f3bb003fc9c1", + "services": [ + "SAP", + "Entra" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "Monitor CPU and memory utilization of the nodes" + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "1a4835ac-9422-423e-ae80-b123081a5417", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/configure-azure-cni", + "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": [ + "SAP", + "Entra" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "If using Azure CNI, monitor % of pod IPs consumed per node" + "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": "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, - "link": "https://learn.microsoft.com/azure/virtual-machines/premium-storage-performance", + "category": "Identity and Access", + "checklist": "Azure Landing Zone Review", + "guid": "23181aa4-1742-4694-9ff8-ae7d7d474317", + "services": [ + "SAP", + "Entra", + "AKV" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "Monitor OS disk queue depth in nodes" + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "be209d39-fda4-4777-a424-d116785c2fa5", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/load-balancer-standard", + "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": [ + "SAP", + "Entra", + "AKV" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Monitoring", - "text": "If not using egress filtering with AzFW/NVA, monitor standard ALB allocated SNAT ports" + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "74c2ee76-569b-4a79-a57e-dedf91b022c9", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/aks-resource-health", + "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": [ + "SAP", + "Entra" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Subscribe to resource health notifications for your AKS cluster" + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "b54eb2eb-03dd-4aa3-9927-18e2edb11726", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", - "severity": "High", - "simple": -1, - "subcategory": "Resources", - "text": "Configure requests and limits in your pod specs" + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "769ef669-1a48-435a-a942-223ece80b123", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", + "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": [ + "SAP", + "Entra" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Resources", - "text": "Enforce resource quotas for namespaces" + "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": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "081a5417-4158-433e-a3ad-3c2de733165c", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", - "severity": "High", - "subcategory": "Resources", - "text": "Ensure your subscription has enough quota to scale out your nodepools" + "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": [ + "SAP", + "Entra" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "For applications that access SAP, you might want to use principal propagation to establish SSO." }, { - "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, - "link": "https://learn.microsoft.com/azure/aks/concepts-scale", + "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": [ + "SAP", + "Entra" + ], "severity": "Medium", - "subcategory": "Scalability", - "text": "Use the Cluster Autoscaler" + "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": "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, - "link": "https://learn.microsoft.com/azure/aks/custom-node-configuration", - "severity": "Low", - "subcategory": "Scalability", - "text": "Customize node configuration for AKS node pools" + "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": [ + "SAP", + "Entra" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "Implement SSO to SAP BTP" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "faa19bfe-9d55-4d04-a3c4-919ca1b2d121", - "link": "https://learn.microsoft.com/azure/aks/concepts-scale", - "scale": 1, + "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": [ + "SAP", + "Entra" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Scalability", - "text": "Use the Horizontal Pod Autoscaler when required" + "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": "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", - "link": "https://blog.cloudtrooper.net/2020/10/23/which-vm-size-should-i-choose-as-aks-node/", + "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": [ + "AzurePolicy", + "Subscriptions", + "SAP" + ], + "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": "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": [ + "Subscriptions", + "SAP" + ], "severity": "High", - "subcategory": "Scalability", - "text": "Consider an appropriate node size, not too large or too small" + "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": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "38800e6a-ae01-40a2-9fbc-ae5a06e5462d", - "link": "https://learn.microsoft.com/azure/aks/quotas-skus-regions#service-quotas-and-limits", - "severity": "Low", - "subcategory": "Scalability", - "text": "If required for scalability consider adding more than 5000 nodes" + "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": [ + "Subscriptions" + ], + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "9583c0f6-6083-43f6-aa6b-df7102c901bb", - "link": "https://learn.microsoft.com/azure/event-grid/event-schema-aks", - "severity": "Low", - "subcategory": "Scalability", - "text": "Consider subscribing to EventGrid Events for AKS automation" - }, - { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "c5016d8c-c6c9-4165-89ae-673ef0fff19d", - "link": "https://learn.microsoft.com/azure/aks/manage-abort-operations", - "severity": "Low", - "subcategory": "Scalability", - "text": "For long running operation on an AKS cluster consider event termination" + "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": [ + "Subscriptions", + "VM" + ], + "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" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": 1, - "guid": "c4e37133-f186-4ce1-aed9-9f1b32f6e021", - "link": "https://learn.microsoft.com/azure/aks/use-azure-dedicated-hosts", + "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": [ + "Subscriptions" + ], "severity": "Low", - "subcategory": "Scalability", - "text": "If required consider using Azure Dedicated Hosts for AKS nodes" + "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": "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", - "link": "https://learn.microsoft.com/azure/aks/cluster-configuration", - "scale": 1, + "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": [ + "Subscriptions", + "VM" + ], "severity": "High", - "subcategory": "Storage", - "text": "Use ephemeral OS disks" + "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": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "fc4972cc-3cd2-45bf-a707-6e9eab4bed32", - "link": "https://learn.microsoft.com/azure/virtual-machines/disks-types", - "scale": 1, + "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": [ + "Subscriptions" + ], "severity": "High", - "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" + "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": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "39c486ce-d5af-4062-89d5-18bb5fd795db", - "link": "https://learn.microsoft.com/azure/aks/use-ultra-disks", - "scale": 1, - "severity": "Low", - "subcategory": "Storage", - "text": "For hyper performance storage option use Ultra Disks on AKS" + "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": [ + "Cost", + "TrafficManager", + "Subscriptions" + ], + "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": "Operations", - "checklist": "Azure AKS Review", - "guid": "9f7547c1-747d-4c56-868a-714435bd19dd", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-multi-region", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "14591147-5e39-4e53-89cc-cd979366bcda", + "services": [ + "SQL", + "SAP", + "Monitor" + ], "severity": "Medium", - "simple": -1, - "subcategory": "Storage", - "text": "Avoid keeping state in the cluster, and store data outside (AzStorage, AzSQL, Cosmos, etc)" + "subcategory": "Monitoring", + "text": "Use SAP Solution Manager and Azure Monitor for SAP Solutions to monitor SAP HANA, high-availability SUSE clusters, and SQL systems" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "cost": -1, - "guid": "24429eb7-2281-4376-85cc-57b4a4b18142", - "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-storage", - "scale": 1, + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "2750ab1a-b039-4d95-b54c-7c8929cb107d", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "Monitor", + "SAP", + "Entra", + "VM" + ], "severity": "Medium", - "subcategory": "Storage", - "text": "If using AzFiles Standard, consider AzFiles Premium and/or ANF for performance reasons" + "subcategory": "Monitoring", + "text": "Run a VM Extension for SAP check. VM Extension for SAP uses the assigned managed identity of a virtual machine to access VM monitoring and configuration data.", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" }, { - "category": "Operations", - "checklist": "Azure AKS Review", - "guid": "83958a8c-2689-4b32-ab57-cfc64546135a", - "ha": 1, - "link": "https://learn.microsoft.com/azure/aks/availability-zones#azure-disk-availability-zone-support", + "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": [ + "AzurePolicy", + "Monitor" + ], "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" + "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": "Management", - "checklist": "Azure API Management Review", - "guid": "06862505-2d9a-4874-9491-2837b00a3475", - "link": "https://learn.microsoft.com/azure/api-management/backends", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "2f7c95f0-6e15-44e3-aa35-92829e6e2061", + "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", + "services": [ + "Storage", + "Backup", + "Monitor" + ], "severity": "Medium", - "subcategory": "Best practices", - "text": "Use Backends feature to eliminate redundant API backend configurations" + "subcategory": "Monitoring", + "text": "Protect your HANA database with Azure Backup service. If you deploy Azure NetApp Files (ANF) for your HANA database, use the Azure Application Consistent Snapshot tool (AzAcSnap) to take application-consistent snapshots", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" }, { - "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", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "73686af4-6791-4f89-95ad-a43324e13811", + "link": "https://learn.microsoft.com/azure/automation/update-management/overview", + "services": [ + "Monitor", + "SAP", + "VM" + ], "severity": "Medium", - "subcategory": "Best practices", - "text": "Use Named Values to store common values that can be used in policies" + "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.", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/" }, { - "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", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "523181aa-4174-4269-93ff-8ae7d7d47431", + "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", + "services": [ + "Monitor", + "SAP", + "NetworkWatcher" + ], "severity": "Medium", - "subcategory": "Business continuity and disaster recovery", - "text": "Deploy to multiple Azure regions" + "subcategory": "Monitoring", + "text": "Use Network Watcher Connection Monitor to monitor SAP database and application server latency metrics, or collect and display network latency measurements with Azure Monitor.", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" }, { - "category": "Management", - "checklist": "Azure API Management Review", - "guid": "9c8d1664-dd9a-49d4-bd83-950af0af4044", - "link": "https://learn.microsoft.com/azure/api-management/high-availability", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "76c8bcbf-45bb-4e60-ad8a-03e97778424d", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", + "services": [ + "Monitor", + "SAP" + ], "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": "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/learn/paths/implement-resource-mgmt-security/" }, { - "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", - "severity": "High", - "subcategory": "Business continuity and disaster recovery", - "text": "Ensure there is an automated backup routine" + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "616785d6-fa96-4c96-ad88-518f482734c8", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "Subscriptions", + "Monitor", + "SAP" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "For each Azure subscription, run an Azure Availability Zone latency test before zonal deployment to choose low-latency zones for SAP on Azure deployment." }, { - "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", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "86ba2802-1459-4114-95e3-9e5309cccd97", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "services": [ + "Monitor", + "SAP", + "Sentinel" + ], "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": "Implement threat protection for SAP with Microsoft Sentinel." }, { - "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", - "severity": "Low", - "subcategory": "Performance and scalability", - "text": "If you need to log at high performance levels, consider Event Hubs policy" + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "4d116785-d2fa-456c-96ad-48408fe72734", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "ACR", + "VM", + "AzurePolicy", + "Entra", + "Monitor" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Enforcing configuration of update management through policy ensures all VMs are included in the patch management regimen, provides application teams with the ability to manage patch deployment for their VMs, and provides central IT with visibility and enforcement capabilities across all VMs" }, { - "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", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "c486ba28-0dc0-4591-af65-de8e1309cccd", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", + "services": [ + "Monitor", + "SAP", + "VM" + ], "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": "Enable VM Insights for VM's running SAP Workloads." }, { - "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", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "579266bc-ca27-45fa-a1ab-fe9d55d04c3c", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", + "services": [ + "Cost", + "Monitor" + ], "severity": "Medium", - "subcategory": "Performance and scalability", - "text": "Configure autoscaling to scale out the number of instances when the load increases" + "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." }, { - "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", + "category": "Management and Monitoring", + "checklist": "Azure Landing Zone Review", + "guid": "4919cb1b-3d13-425a-b124-ba34df685edd", + "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", + "services": [ + "Monitor" + ], "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": " " }, { - "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": "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": [ + "AppGW", + "AzurePolicy", + "WAF" + ], "severity": "Medium", - "subcategory": "Development best practices", - "text": "Implement an error handling policy at the global level" + "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/learn/paths/secure-application-delivery/" }, { - "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "a3592829-e6e2-4061-9368-6af46791f893", + "link": "https://learn.microsoft.com/azure/networking/", + "services": [ + "ACR", + "VNet", + "SAP" + ], "severity": "Medium", - "subcategory": "Development best practices", - "text": "Ensure all APIs policies include a element." + "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/learn/modules/design-implement-azure-expressroute/" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "a5c45b03-93b6-42fe-b16b-8fccb6a79902", - "link": "https://learn.microsoft.com/azure/api-management/policy-fragments", + "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": [ + "VNet", + "SAP", + "VM" + ], "severity": "Medium", - "subcategory": "Development best practices", - "text": "Use Policy Fragments to avoid repeating same policies definitions across multiple APIs" + "subcategory": "IP plan", + "text": "Public I.P assignment to VM running SAP Workload is not recommended.", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" }, { - "category": "Governance", - "checklist": "Azure API Management Review", - "guid": "c3818a95-6ff3-4474-88dc-e809b46dad6a", - "link": "https://learn.microsoft.com/azure/api-management/monetization-support", + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "9cccd979-366b-4cda-8750-ab1ab039d95d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "services": [ + "VNet", + "ASR" + ], "severity": "Medium", - "subcategory": "Monetization", - "text": "If you are planning to monetize your APIs, review the 'monetization support' article for best practices" + "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": "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", - "severity": "High", - "subcategory": "Monitoring", - "text": "Enable Diagnostics Settings to export logs to Azure Monitor" + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "54c7c892-9cb1-407d-9325-ae525ba34d46", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "services": [ + "VNet" + ], + "severity": "Medium", + "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/" }, { - "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "85e2213a-ce7b-4b12-8f7c-95f06e154e3a", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "services": [ + "VNet", + "VM" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable Application Insights for more detailed telemetry" + "subcategory": "IP plan", + "text": "Ensure Accelerated Networking is enable for all VM where it is applicable.", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/" }, { - "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", - "severity": "High", - "subcategory": "Monitoring", - "text": "Configure alerts on the most critical metrics" + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d8a03e97-7784-424d-9167-85d6fa96c96a", + "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "services": [ + "Firewall" + ], + "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/learn/paths/secure-networking-infrastructure/" }, { - "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", - "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d88518f4-8273-44c8-a6ba-280214591147", + "link": "https://learn.microsoft.com/azure/firewall/", + "services": [ + "AppGW", + "SAP" + ], + "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.", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" }, { - "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", - "severity": "High", - "subcategory": "Identity", - "text": "Protect incoming requests to APIs (data plane) with Azure AD" + "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": [ + "ACR", + "FrontDoor", + "AzurePolicy", + "WAF" + ], + "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/" }, { - "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "b039d95d-54c7-4c89-89cb-107d5325ae52", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "AppGW", + "FrontDoor", + "AzurePolicy", + "WAF" + ], "severity": "Medium", - "subcategory": "Identity", - "text": "Use Azure AD to authenticate users in the Developer Portal" + "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/" }, { - "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5ada4332-4e13-4811-9231-81aa41742694", + "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", + "services": [ + "AppGW", + "WAF", + "LoadBalancer" + ], "severity": "Medium", - "subcategory": "Privileged access", - "text": "Create appropriate groups to control the visibility of the products" + "subcategory": "PaaS", + "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/learn/paths/implement-network-security/?source=learn" }, { "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", + "checklist": "Azure Landing Zone Review", + "guid": "3ff8ae7d-7d47-4431-96c8-bcbf45bbe609", + "services": [ + "LoadBalancer" + ], "severity": "Medium", - "subcategory": "Security", - "text": "Deploy the service within a Virtual Network (VNET)" + "subcategory": "PaaS", + "text": "Ensure that internal deployments for Azure Load Balancer are set up to use Direct Server Return (DSR) for HA configuration on the DBMS layer" }, { "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", + "checklist": "Azure Landing Zone Review", + "guid": "6e154e3a-a359-4282-ae6e-206173686af4", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/organize-resources?tabs=AzureManagementGroupsAndHierarchy", + "services": [ + "VNet", + "Storage", + "SAP" + ], "severity": "Medium", - "subcategory": "Security", - "text": "Deploy network security groups (NSG) to your subnets to restrict or monitor traffic" + "subcategory": "Segmentation", + "text": "If Azure NetApp Files is used for SAP deployment , ensure that only one delegate subnet can exist in a Vnet for Azure NetAppFiles", + "training": "https://learn.microsoft.com/learn/paths/implement-network-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", + "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": [ + "VNet", + "SAP" + ], "severity": "Medium", - "subcategory": "Security", - "text": "Deploy Private Endpoints to filter incoming traffic when VNET is not used" + "subcategory": "Segmentation", + "text": "Use NSGs and application security groups to micro-segment traffic within SAP application layer, like App subnet, DB subnet and Web subnet etc.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/" }, { "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", - "severity": "High", - "subcategory": "Security", - "text": "Disable Public Network Access" + "checklist": "Azure Landing Zone Review", + "guid": "41742694-3ff8-4ae7-b7d4-743176c8bcbf", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "services": [ + "NVA", + "SAP" + ], + "severity": "Medium", + "subcategory": "Segmentation", + "text": "It is not supported to deploy any NVA between SAP application and SAP Database server", + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/" }, { "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", + "checklist": "Azure Landing Zone Review", + "guid": "45bbe609-d8a0-43e9-9778-424d616785d6", + "services": [ + "VNet", + "SAP" + ], "severity": "Medium", - "subcategory": "Connectivity", - "text": "Use Azure Front Door for multi-region deployment" + "subcategory": "Segmentation", + "text": "Placing of the SAP application layer and SAP DBMS in different Azure VNets that aren't peered isn't supported" }, { - "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "fa96c96a-d885-418f-9827-34c886ba2802", + "services": [ + "SAP" + ], "severity": "Medium", - "subcategory": "Automation", - "text": "Simplify management with PowerShell automation scripts" + "subcategory": "Segmentation", + "text": "For optimal network latency with SAP applications, consider using Azure proximity placement groups." }, { - "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", - "severity": "Medium", - "subcategory": "Best practices", - "text": "Review DevOps best practices from the Cloud Adaption Framework APIM Landing Zone Accelerator" + "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", + "services": [ + "Subscriptions", + "RBAC", + "SAP" + ], + "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": "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", + "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", + "services": [ + "PrivateLink", + "SAP", + "NVA" + ], "severity": "Medium", - "subcategory": "Best practices", - "text": "Promote usage of Visual Studio Code APIM extension for faster API development" + "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": "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": "Security, Governance and Compliance", + "checklist": "Azure Landing Zone Review", + "guid": "cf65de8e-1309-4ccc-b579-266bcca275fa", + "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "SAP", + "SQL", + "Backup", + "Storage" + ], "severity": "Medium", - "subcategory": "DevOps", - "text": "Implement DevOps and CI/CD in your workflow" + "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": "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", + "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", + "services": [ + "Storage" + ], "severity": "Medium", - "subcategory": "APIs", - "text": "Secure APIs using client certificate authentication" + "subcategory": "Governance", + "text": "Azure Storage encryption is enabled by default" }, { - "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", + "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": [], "severity": "Medium", - "subcategory": "APIs", - "text": "Secure backend services using client certificate authentication" + "subcategory": "Governance", + "text": " " }, { - "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", - "severity": "Medium", - "subcategory": "APIs", - "text": "Review 'Recommendations to mitigate OWASP API Security Top 10 threats' article and check what is applicable to your APIs" + "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": "Security", - "checklist": "Azure API Management Review", - "guid": "5507c4b8-a7f8-41d6-9661-418c987100c9", - "link": "https://learn.microsoft.com/azure/api-management/authorizations-overview", + "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", + "services": [ + "AKV" + ], + "severity": "High", + "subcategory": "Secrets", + "text": "Use Azure Key Vault to store your secrets and credentials" + }, + { + "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", + "services": [ + "AKV" + ], "severity": "Medium", - "subcategory": "APIs", - "text": "Use Authorizations feature to simplify management of OAuth 2.0 token for your backend APIs" + "subcategory": "Secrets", + "text": "It is recommended to LOCK the Azure Resources post successful deployment to safeguard against unauthorized changes" }, { - "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", - "severity": "High", - "subcategory": "Ciphers", - "text": "Use the latest TLS version when encrypting information in transit. Disable outdated and unnecessary protocols and ciphers when possible." + "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", + "services": [ + "AzurePolicy", + "AKV" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." }, { - "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", - "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" + "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", + "services": [ + "AzurePolicy", + "RBAC", + "AKV" + ], + "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" }, { - "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", + "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", + "services": [ + "AzurePolicy", + "Defender", + "SAP", + "AKV" + ], "severity": "Medium", - "subcategory": "Identities", - "text": "Use managed identities to authenticate to other Azure resources whenever possible" + "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": "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", - "severity": "High", - "subcategory": "Network", - "text": "Use web application firewall (WAF) by deploying Application Gateway in front of APIM" + "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", + "services": [ + "RBAC", + "SAP", + "AKV" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": "Delegate an SAP admin custom role with just-in-time access." + }, + { + "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", + "services": [ + "SAP", + "AKV" + ], + "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" + }, + { + "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", + "services": [ + "SAP", + "Entra", + "AKV" + ], + "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" + }, + { + "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", + "services": [ + "SAP", + "AKV" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": "Make sure you harden the operating system to eradicate vulnerabilities that could lead to attacks on the SAP database." + }, + { + "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", + "services": [ + "AKV" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." + }, + { + "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", + "services": [ + "AKV" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": "Use an Azure Key Vault per application per environment per region." + }, + { + "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", + "services": [ + "AKV" + ], + "severity": "Medium", + "subcategory": "Secrets", + "text": " " + }, + { + "category": "Storage", + "checklist": "Azure Landing Zone Review", + "guid": "d579266b-cca2-475f-aa1a-bfe9d55d04c3", + "services": [ + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": " ", + "text": "Disk config for Oracle, SQL, HANA" }, { "category": "Security", @@ -1739,6 +3489,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", + "services": [ + "AppSvc", + "AKV" + ], "severity": "High", "subcategory": "Data Protection", "text": "Use Key Vault to store secrets" @@ -1749,6 +3503,11 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/app-service-key-vault-references", + "services": [ + "AppSvc", + "Entra", + "AKV" + ], "severity": "High", "subcategory": "Data Protection", "text": "Use Managed Identity to connect to Key Vault" @@ -1759,6 +3518,10 @@ "description": "Store the App Service TLS certificate in Key Vault.", "guid": "f8d39fda-4776-4831-9c11-5775c2ea55b4", "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-certificate", + "services": [ + "AppSvc", + "AKV" + ], "severity": "High", "subcategory": "Data Protection", "text": "Use Key Vault to store TLS certificate." @@ -1769,6 +3532,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/overview-hosting-plans", + "services": [ + "Subscriptions", + "AppSvc" + ], "severity": "Medium", "subcategory": "Data Protection", "text": "Isolate systems that process sensitive information" @@ -1779,6 +3546,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/operating-system-functionality#file-access", + "services": [ + "TrafficManager", + "AppSvc" + ], "severity": "Medium", "subcategory": "Data Protection", "text": "Do not store sensitive data on local disk" @@ -1789,6 +3560,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/overview-authentication-authorization", + "services": [ + "AppSvc", + "Entra" + ], "severity": "Medium", "subcategory": "Identity and Access Control", "text": "Use an established Identity Provider for authentication" @@ -1799,6 +3574,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/deploy-best-practices", + "services": [ + "AppSvc", + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Control", "text": "Deploy from a trusted environment" @@ -1809,6 +3588,9 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/deploy-configure-credentials#disable-basic-authentication", + "services": [ + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Control", "text": "Disable basic authentication" @@ -1819,6 +3601,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/overview-managed-identity?tabs=portal%2Chttp", + "services": [ + "Entra", + "AKV" + ], "severity": "High", "subcategory": "Identity and Access Control", "text": "Use Managed Identity to connect to resources" @@ -1829,6 +3615,10 @@ "description": "Where using images stored in Azure Container Registry, pull these using a Managed Identity.", "guid": "d9a25827-18d2-4ddb-8072-5769ee6691a4", "link": "https://learn.microsoft.com/azure/app-service/configure-custom-container#use-managed-identity-to-pull-image-from-azure-container-registry", + "services": [ + "ACR", + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Control", "text": "Pull containers using a Managed Identity" @@ -1839,6 +3629,11 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/troubleshoot-diagnostic-logs", + "services": [ + "Entra", + "Monitor", + "AppSvc" + ], "severity": "Medium", "subcategory": "Logging and Monitoring", "text": "Send App Service runtime logs to Log Analytics" @@ -1849,6 +3644,11 @@ "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", "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "services": [ + "Entra", + "Monitor", + "AppSvc" + ], "severity": "Medium", "subcategory": "Logging and Monitoring", "text": "Send App Service activity logs to Log Analytics" @@ -1859,6 +3659,12 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/overview-vnet-integration", + "services": [ + "VNet", + "Monitor", + "NVA", + "Firewall" + ], "severity": "Medium", "subcategory": "Network Security", "text": "Outbound network access should be controlled" @@ -1869,6 +3675,13 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/networking/nat-gateway-integration", + "services": [ + "PrivateLink", + "NVA", + "VNet", + "Storage", + "Firewall" + ], "severity": "Low", "subcategory": "Network Security", "text": "Ensure a stable IP for outbound communications towards internet addresses" @@ -1879,6 +3692,10 @@ "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", "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" @@ -1889,6 +3706,13 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/networking/app-gateway-with-service-endpoints", + "services": [ + "FrontDoor", + "AppSvc", + "WAF", + "AppGW", + "Monitor" + ], "severity": "High", "subcategory": "Network Security", "text": "Use a WAF in front of App Service" @@ -1899,6 +3723,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/networking-features#access-restrictions", + "services": [ + "PrivateLink", + "WAF" + ], "severity": "High", "subcategory": "Network Security", "text": "Avoid for WAF to be bypassed" @@ -1910,6 +3738,10 @@ "graph": "appserviceresources | where type =~ 'microsoft.web/sites/config' | extend compliant = (properties.MinTlsVersion>=1.2) | distinct id,compliant", "guid": "c115775c-2ea5-45b4-9ad4-8408ee72734b", "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-tls-versions", + "services": [ + "AzurePolicy", + "AppSvc" + ], "severity": "Medium", "subcategory": "Network Security", "text": "Set minimum TLS policy to 1.2" @@ -1921,6 +3753,10 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/configure-ssl-bindings#enforce-https", + "services": [ + "AppSvc", + "WAF" + ], "severity": "High", "subcategory": "Network Security", "text": "Use HTTPS only" @@ -1931,6 +3767,9 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/app-service-web-tutorial-rest-api", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Network Security", "text": "Wildcards must not be used for CORS" @@ -1942,6 +3781,7 @@ "graph": "appserviceresources | where type =~ 'microsoft.web/sites/config' | extend compliant = (properties.RemoteDebuggingEnabled == false) | distinct id,compliant", "guid": "d9bd3baf-cda3-4b54-bb2e-b03dd9a25827", "link": "https://learn.microsoft.com/azure/app-service/configure-common#configure-general-settings", + "services": [], "severity": "High", "subcategory": "Network Security", "text": "Turn off remote debugging" @@ -1952,6 +3792,10 @@ "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", "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-app-service-introduction", + "services": [ + "Defender", + "AppSvc" + ], "severity": "Medium", "subcategory": "Network Security", "text": "Enable Defender for Cloud - Defender for App Service" @@ -1962,6 +3806,14 @@ "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", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "services": [ + "WAF", + "AppGW", + "NVA", + "DDoS", + "VNet", + "EventHubs" + ], "severity": "Medium", "subcategory": "Network Security", "text": "Enable DDOS Protection Standard on the WAF VNet" @@ -1972,6 +3824,11 @@ "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", "link": "https://learn.microsoft.com/azure/app-service/configure-custom-container#use-an-image-from-a-network-protected-registry", + "services": [ + "ACR", + "VNet", + "PrivateLink" + ], "severity": "Medium", "subcategory": "Network Security", "text": "Pull containers over a Virtual Network" @@ -1982,6 +3839,7 @@ "description": "Conduct a penetration test on the web application following the penetration testing rules of engagement.", "guid": "eb2eb03d-d9a2-4582-918d-2ddb10725769", "link": "https://learn.microsoft.com/azure/security/fundamentals/pen-testing", + "services": [], "severity": "Medium", "subcategory": "Penetration Testing", "text": "Conduct a penetration test" @@ -1992,6 +3850,7 @@ "description": "Deploy trusted code that was validated and scanned for vulnerabilities according to DevSecOps practices.", "guid": "19aed9c5-5d04-4c2c-9919-ca0b2c12159e", "link": "https://learn.microsoft.com/azure/architecture/solution-ideas/articles/devsecops-in-azure", + "services": [], "severity": "Medium", "subcategory": "Vulnerability Management", "text": "Deploy validated code" @@ -2002,1930 +3861,2920 @@ "description": "Use the latest versions of supported platforms, programming languages, protocols, and frameworks.", "guid": "114b933d-f574-4ecc-ad9b-d3bafcda3b54", "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" }, { - "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", - "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 Arc Review", + "description": "Define a resource group structure for placement of Azure Arc-enabled servers resources", + "guid": "585e1112-9bd7-4ba0-82f7-b94ef6e043d2", + "services": [ + "Arc" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "One or more resource groups is required for onboarding servers into Azure", + "waf": "Operations" }, { - "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": "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": [ + "Arc", + "Entra" + ], "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/" + "subcategory": "Capacity Planning", + "text": "Take Azure Active Directory object limitations into account", + "waf": "Performance" }, { - "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", - "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": "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": [ + "Arc", + "Subscriptions" + ], + "severity": "High", + "subcategory": "General", + "text": "Has the Resource providers required been registered in all subscriptions", + "waf": "Operations" }, { - "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", - "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/" + "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": [ + "Arc" + ], + "severity": "Low", + "subcategory": "General", + "text": "Has a tagging strategy for Azure Arc-enabled servers been defined", + "waf": "Cost" }, { - "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": "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": [ + "Arc" + ], "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": "General", + "text": "What operating systems need to be Azure Arc-enabled", + "waf": "Operations" }, { - "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", - "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": "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": [ + "Arc" + ], + "severity": "High", + "subcategory": "General", + "text": "Are required software installed on Windows and Linux servers to support the installation", + "waf": "Operations" }, { - "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", - "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": "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": [ + "Arc" + ], + "severity": "High", + "subcategory": "General", + "text": "Make sure to use a supported Azure region", + "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": "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": [ + "Arc", + "Subscriptions" + ], + "severity": "Low", + "subcategory": "Organization", + "text": "Define the structure for Azure management of resources", + "waf": "Performance" + }, + { + "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", + "services": [ + "Arc", + "RBAC", + "Entra" + ], "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": "Access", + "text": "Assign RBAC rights to Azure AD user/group access for managing Azure Arc-enabled servers", + "waf": "Security" }, { - "category": "BC/DR", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD control plan does not offer a financially backed service level agreement. We strive to attain at least 99.9% availability for the Windows 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", - "link": "https://azure.microsoft.com/support/legal/sla/virtual-desktop/v1_0/", + "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", + "services": [ + "Arc", + "Entra", + "AKV" + ], + "severity": "Low", + "subcategory": "Access", + "text": "Consider using managed identities for applications to access Azure resources like Key Vault example in link", + "waf": "Security" + }, + { + "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": [ + "Arc", + "Subscriptions", + "Entra" + ], "severity": "High", - "subcategory": "Compute", - "text": "Determine the expected High Availability SLA for applications/desktops published through AVD" + "subcategory": "Requirements", + "text": "An Azure Active Directory tenant must be available with at least one subscription", + "waf": "Operations" }, { - "category": "BC/DR", - "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.", - "guid": "6acc076e-f9b1-441a-a989-579e76b897e7", - "link": "https://learn.microsoft.com/azure/virtual-desktop/disaster-recovery", + "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": [ + "Arc", + "RBAC", + "Entra" + ], "severity": "Medium", - "subcategory": "Compute", - "text": "Assess Geo Disaster Recovery region for AVD Host Pools" + "subcategory": "Requirements", + "text": "Define which users (AAD user/groups) has access to onboard Azure Arc-enabled servers", + "waf": "Security" }, { - "category": "BC/DR", - "checklist": "Azure Virtual Desktop Review", - "description": "Before approaching Windows Virtual Desktop BCDR planning and design, it is important to initially consider which applications are 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/disaster-recovery", + "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": [ + "Arc", + "RBAC", + "Entra" + ], "severity": "Medium", - "subcategory": "Compute", - "text": "Separate critical applications in different AVD Host Pools" - }, - { - "category": "BC/DR", - "checklist": "Azure Virtual Desktop Review", - "description": "? Did you select the proper resiliency level for your Host Pool VMs (Availability Set vs. Availability Zones)?? Are you aware of implications on HA SLA and scalability limits that come with AS or AZ? ? You can currently deploy 399 VMs per Windows Virtual Desktop ARM template deployment without Availability Sets, or 200 VMs per Availability Set.? You can increase the number of VMs per deployment by switching off Availability Sets in either the ARM template or the Azure portal host pool enrollment.Deploying AZ is now possible, one AZ at time at the moment, need to manually create a fraction of VMs in each desired AZ. ", - "guid": "25ab225c-6f4e-4168-9fdd-dea8a4b7cdeb", - "link": "https://learn.microsoft.com/azure/virtual-desktop/faq", - "severity": "High", - "subcategory": "Compute", - "text": "Plan the best resiliency option for AVD Host Pool deployment" + "subcategory": "Security", + "text": "Use the principle of least privileged", + "waf": "Security" }, { - "category": "BC/DR", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Backup can be used also to protect Host Pool VMs, this practice is supported, even if Host Pool VMs should be stateless. This option could be considered for Personal Host Pools. ", - "guid": "4c61fc3f-c14e-4ea6-b69e-8d9a3eec218e", - "link": "https://learn.microsoft.com/azure/virtual-desktop/disaster-recovery", + "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": [ + "Arc", + "RBAC", + "Entra" + ], "severity": "Medium", - "subcategory": "Compute", - "text": "Assess the requirement to backup AVD Session Hosts" - }, - { - "category": "BC/DR", - "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, even if in case of a major disaster. 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.", - "guid": "dd2e0d5d-771d-441e-9610-cc57b4a4a141", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/shared-images-portal", - "severity": "Low", - "subcategory": "Dependencies", - "text": "Plan for Golden Image cross-region availability" + "subcategory": "Security", + "text": "How many Service Principals are needed for onboarding Arc-enabled servers into Azure", + "waf": "Security" }, { - "category": "BC/DR", - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/disaster-recovery", + "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": [ + "Arc", + "RBAC", + "Entra" + ], "severity": "Medium", - "subcategory": "Dependencies", - "text": "Assess Infrastructure & Application dependencies " + "subcategory": "Security", + "text": "Limit the rights to onboard Azure Arc-enabled servers to the desired resource groups", + "waf": "Security" }, { - "category": "BC/DR", - "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", - "link": "https://learn.microsoft.com/fslogix/manage-profile-content-cncpt", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Storage", - "text": "Assess which data need to be protected inside the Profile and Office Containers" + "subcategory": "Management", + "text": "Define a strategy for agent provisioning", + "waf": "Operations" }, { - "category": "BC/DR", - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/disaster-recovery", - "severity": "Medium", - "subcategory": "Storage", - "text": "Build a backup protection strategy for Profile and Office Containers" + "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": [ + "Arc", + "Monitor" + ], + "severity": "High", + "subcategory": "Management", + "text": "Define a strategy for agent updates", + "waf": "Operations" }, { - "category": "BC/DR", - "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, or Azure Files Sync for VM-based file servers? 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:? User Profile or Office containers data availability required high-availability SLA is critical and need to be resilient to region failure.? 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.? 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/disaster-recovery", + "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": [ + "Arc", + "AzurePolicy", + "Monitor" + ], "severity": "Medium", - "subcategory": "Storage", - "text": "Assess Profile Container storage replication requirements and resiliency for BCDR purpose" + "subcategory": "Management", + "text": "Define a strategy for extension installation", + "waf": "Operations" }, { - "category": "BC/DR", - "checklist": "Azure Virtual Desktop Review", - "description": "Geo Disaster Recovery: Azure NetApp Files is essentially is LRS (locally replicated storage), then you need to architect something more if you want cross-region replication. The recommendation for cross-region at the moment is NetApp Cloud Sync, replicating to another Azure region (and NetApp Volume). Backup: Backups are handled by snapshots, but are not automatic, need to scheduled using policies. https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-manage-snapshots. There is a maximum limit of snapshots (255) per volume as documented here: https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-resource-limits.", - "guid": "23429db7-2281-4376-85cc-57b4a4b18142", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/azure-netapp-files-manage-snapshots", - "severity": "Medium", - "subcategory": "Storage", - "text": "Review Azure NetApp Files DR strategy" + "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": [ + "Arc", + "Monitor" + ], + "severity": "High", + "subcategory": "Management", + "text": "Define a strategy for extension updates", + "waf": "Operations" }, { - "category": "BC/DR", - "checklist": "Azure Virtual Desktop Review", - "description": "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, when using Azure File Share Premium, replication with FSLogix Cloud Cache should be evaluated, or 'in-region' Availability Zone (AZ) only resiliency should be considered. Backup: Azure Backup fully supports Azure File Share all SKUs, and is the recommended solution to protect Profile Containers. If using OneDrive or other external storage, saving user Profile and/or Office Containers data maybe not necessary.", - "guid": "3d4f3537-c134-46dc-9602-7a71efe1bd05", - "link": "https://learn.microsoft.com/azure/backup/backup-afs", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Storage", - "text": "Review Azure Files DR strategy" + "subcategory": "Management", + "text": "Consider using Azure Automanage to control settings and avoid configuration drift on servers", + "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 distributing to hosts after pool deployment using traditional SW distribution methods.", - "guid": "86ba2802-1459-4014-95d3-8e5309ccbd97", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-customize-master-image", + "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": [ + "Arc", + "Monitor" + ], "severity": "High", - "subcategory": "Golden Image/s", - "text": "Determine how applications will be deployed in AVD Host Pools" + "subcategory": "Monitoring", + "text": "Monitor for unresponsive agents", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Will they use fslogix application masking which would lend itself to a single image, or multi images with different applications baked in: what is necessitating more than one image to be used?", - "guid": "9266bcca-274f-4aa1-abf3-9d95d44c7c89", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Golden Image/s", - "text": "Estimate the number of golden images that will be required" + "subcategory": "Monitoring", + "text": "Design a monitoring strategy to send metrics and logs to an Log Analytics workspace", + "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Golden Image/s", - "text": "Determine which OS image/s you will use for Host Pool deployment" - }, - { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "If nothing exists, consider using Azure Image Builder to automate the build process. ", - "guid": "9bd7bb01-2f7b-495e-86e1-54e2aa359282", - "link": "https://learn.microsoft.com/azure/virtual-machines/image-builder-overview", - "severity": "Low", - "subcategory": "Golden Image/s", - "text": "If a custom image will be used, determine if there is an automated build process?" - }, - { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Evaluate Azure Compute Gallery.", - "guid": "5a2adb2c-3e23-426b-b225-ca44e1696fdd", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/shared-image-galleries", - "severity": "Low", - "subcategory": "Golden Image/s", - "text": "If a custom image will be used, is there a plan to organize and manage the lifecycle of your images?" + "subcategory": "Monitoring", + "text": "Use notification in Activity logs to receive notification on unexpected changes to the resources", + "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-customize-master-image", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Golden Image/s", - "text": "If custom image will be used, check recommended best practices for AVD on how to build master image" + "subcategory": "Monitoring", + "text": "Use Azure Monitor for compliance and operational monitoring", + "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://learn.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", - "link": "https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Golden Image/s", - "text": "Evaluate the usage of Virtual-Desktop-Optimization-Tool" + "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": "Compute", - "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, MEM/Intune, GPO, 3rd-party solutions.", - "guid": "3334fdf9-1c23-4418-8b65-285269440b4b", - "link": "https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session", + "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": [ + "Arc", + "Monitor" + ], "severity": "Low", - "subcategory": "Golden Image/s", - "text": "Plan/Assess AVD Session Host configuration management strategy" + "subcategory": "Security", + "text": "Use Azure Arc-enabled servers to control software updates deployments to servers", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Review article provided and check 'Known Folder Redirection' and 'Files OnDemand' OneDrive features should be considered and eventually adopted.", - "guid": "e3d3e084-4276-4d4b-bc01-5bcf219e4a1e", - "link": "https://learn.microsoft.com/azure/virtual-desktop/install-office-on-AVD-master-image", - "severity": "Medium", - "subcategory": "Golden Image/s", - "text": "Determine if Microsoft OneDrive will be part of AVD deployment" + "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": [ + "Arc" + ], + "severity": "High", + "subcategory": "Networking", + "text": "Define a connectivity method from the server to Azure", + "waf": "Operations" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "Be sure to review this article and use the latest version, review and evaluate Teams exclusions to reduce profile size.", - "guid": "b5887953-5d22-4788-9d30-b66c67be5951", - "link": "https://learn.microsoft.com/azure/virtual-desktop/teams-on-AVD", + "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": [ + "Arc" + ], "severity": "Medium", - "subcategory": "Golden Image/s", - "text": "Determine if Microsoft Teams will be part of AVD deployment" + "subcategory": "Networking", + "text": "Is a proxy server a required for communication over the Public Internet", + "waf": "Operations" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/app-attach-file-share", - "severity": "High", - "subcategory": "MSIX & AppAttach", - "text": "Do not use the same storage account/share as Profile/Office containers " + "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": [ + "Arc", + "VPN", + "PrivateLink", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Is a private (not public Internet) connection required?", + "waf": "Operations" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "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": "MSIX & AppAttach", - "text": "Review performance considerations for MSIX" + "subcategory": "Networking", + "text": "Will Firewall configurations be needed in order to ensure communication with Azure Services?", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/app-attach-file-share", - "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Check proper session host permissions for MSIX share" + "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": [ + "Arc" + ], + "severity": "Low", + "subcategory": "Networking", + "text": "Can the Firewall or Proxy rules be automated updated if Service Tags or IP addresses change", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/app-attach-faq", - "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "MSIX packages for 3rd-party applications" + "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": [ + "Arc" + ], + "severity": "High", + "subcategory": "Networking", + "text": "Always use secure communication for Azure where possible", + "waf": "Security" }, { - "category": "Compute", - "checklist": "Azure Virtual Desktop Review", - "description": "MSIX app attach doesn't support auto-update for MSIX applications, then should be disabled.", - "guid": "bb88037f-5e6b-4fbb-aed5-03547cc447e8", - "link": "https://learn.microsoft.com/azure/virtual-desktop/app-attach-faq", + "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": [ + "Arc", + "Monitor", + "PrivateLink" + ], "severity": "Low", - "subcategory": "MSIX & AppAttach", - "text": "Disable auto-update for MSIX packages" + "subcategory": "Networking", + "text": "Include communication for Azure Arc-enabled Servers extensions in the design (firewall/proxy/private link)", + "waf": "Security" }, { - "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 Enterprise or Windows 10 Enterprise Multi-session, version 2004 or later.", - "guid": "26128a71-f0f1-4cac-9d9e-f1d5e832e42e", - "link": "https://learn.microsoft.com/azure/virtual-desktop/app-attach-faq", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "ac6aae01-e6a8-44de-9df4-7d2d92881b1c", + "link": "https://learn.microsoft.com/azure/governance/policy/", + "services": [ + "Arc", + "AzurePolicy" + ], "severity": "Medium", - "subcategory": "MSIX & AppAttach", - "text": "Review operating systems support" + "subcategory": "Management", + "text": "Use Azure Policy to implement a governance model for hybrid connected servers", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-machines/generation-2", + "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": [ + "Arc" + ], "severity": "Medium", - "subcategory": "Session Host", - "text": "Evaluate the usage of Gen2 VM for Host Pool deployment" - }, - { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Shared/Pooled or Dedicated/Personal", - "guid": "8468c55a-775c-46ee-a5b8-6ad8844ce3b2", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Determine the Host Pool type to use" + "subcategory": "Management", + "text": "Consider using Machine configurations for in guest OS configurations", + "waf": "Operations" }, { - "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.", - "guid": "b38b875b-a1cf-4204-a901-3a5d3ce474db", - "link": "https://learn.microsoft.com/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type", + "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": [ + "Arc", + "AzurePolicy" + ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "For Personal Host Pool type, decide on the assignment type" + "subcategory": "Management", + "text": "Evaluate the need for custom Guest Configuration policies", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Check which one to use and available options, be aware that if autoscaling will be used, it sets it to breadth-first. ", - "guid": "cbd8682a-6abc-4a2a-9fda-1dbf3dc95d48", - "link": "https://learn.microsoft.com/azure/virtual-desktop/host-pool-load-balancing", + "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": [ + "Arc", + "Monitor" + ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "For Pooled Host Pool type, decide on the load balancing method" + "subcategory": "Monitoring", + "text": "Consider using change tracking for tracking changes made on the servers", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Based on your selection criteria, how many Host Pools you would need? You should consider to have multiple ones if:? Multiple OS images? Multiple regions? Different HW required? Different Host Pool type (shared vs. personal)? Different user requirements and SLA (Top users, Execs, Office Worker vs. Developers, etc.)? Different RDP settings (applied at Host Pool level), see https://learn.microsoft.com/azure/virtual-desktop/customize-rdp-properties? Required number of VMs in the host pool exceeding maximum capabilities", - "guid": "c7c791dc-a1f6-4d56-999e-558b937d4985", - "link": "https://learn.microsoft.com/azure/virtual-desktop/environment-setup", - "severity": "High", - "subcategory": "Capacity Planning", - "text": "Estimate the number of different Host Pools to deploy " + "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": [ + "Arc" + ], + "severity": "Medium", + "subcategory": "Requirements", + "text": "Make sure to use an Azure region for storing the metadata approved by the organization", + "waf": "Security" }, { - "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 4 cores for Production is selected per Session Host (multi-session)", - "guid": "e1112dbd-7ba0-412e-9b94-ef6e047d2ea2", - "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "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": [ + "Arc", + "AKV" + ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Run workload performance test to determine the best Azure VM SKU and size to use (determine the number of hosts per pool)" + "subcategory": "Secrets", + "text": "Use Azure Key Vault for certificate management on servers", + "waf": "Security" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "It is critical to check AVD capacity and limits reported in the referenced article. ", - "guid": "992b1cd6-d2f5-44b2-a769-e3a691e8838a", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop", + "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": [ + "Arc", + "Storage", + "Entra", + "AKV" + ], "severity": "High", - "subcategory": "Capacity Planning", - "text": "Verify AVD scalability limits for the environment" + "subcategory": "Secrets", + "text": "What is the acceptable life time of the secret used by SP's", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/configure-vm-gpu", + "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": [ + "Arc", + "AKV" + ], "severity": "Medium", - "subcategory": "Capacity Planning", - "text": "Determine if Session Hosts will require GPU" + "subcategory": "Secrets", + "text": "Secure the public key for Azure Arc-enabled Servers", + "waf": "Security" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Whenever is possible, it is recommended to leverage VM SKUs with Accelerated Networking feature. Today pnly Windows Server OS are supported (see list in the article), in the future Windows Client OS maybe also included. ", - "guid": "b47a393a-0803-4272-a479-8b1578b219a4", - "link": "https://learn.microsoft.com/azure/virtual-network/create-vm-accelerated-networking-powershell", - "severity": "Low", - "subcategory": "Capacity Planning", - "text": "Recommended to use VM SKUs able to leverage Accelerated Networking feature in Azure." + "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": [ + "Arc" + ], + "severity": "High", + "subcategory": "Security", + "text": "Ensure there is local administrator access for executing the agent installation", + "waf": "Security" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "For proper planning and and deployment, it is important to asses the maximum number of users and average concurrent sessions. ", - "guid": "bb91a33d-90ca-4e2c-a881-3706f7c0cb9f", - "link": "https://learn.microsoft.com/azure/virtual-desktop/faq", + "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": [ + "Arc" + ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Assess how many users will connect to AVD and from which regions" + "subcategory": "Security", + "text": "Limit the amount of users with local administrator rights to the servers", + "waf": "Security" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Multiple Host Pools maybe required to support different set of users, it is recommended to estimate how many will be necessary. ", - "guid": "a1cf2049-9013-4a5d-9ce4-74dbcbd8682a", - "link": "https://learn.microsoft.com/azure/virtual-desktop/environment-setup", + "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": [ + "Arc", + "Entra" + ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Determine if all users will have the same set of applications and/or different Host Pool configurations and/or OS images" + "subcategory": "Security", + "text": "Consider using and restricting access to managed identities for applications.", + "waf": "Security" }, { - "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 Express Route, 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", - "severity": "Low", - "subcategory": "Clients & Users", - "text": "Assess external dependencies for each Host Pool" + "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": [ + "Arc", + "Defender" + ], + "severity": "Medium", + "subcategory": "Security", + "text": "Enable Defender for Servers for all servers to secure hybrid workloads from threats", + "waf": "Security" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Review limitations of each client and compare multiple options when possible.", - "guid": "a1f6d565-99e5-458b-a37d-4985e1112dbd", - "link": "https://learn.microsoft.com/azure/virtual-desktop/connect-windows-7-10", + "category": "Security, Governance and Compliance", + "checklist": "Azure Arc Review", + "guid": "cbafe6c4-6589-4d45-9a92-7c3974d1102c", + "services": [ + "Arc" + ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Review client OS used and AVD client type" + "subcategory": "Security", + "text": "Define controls to detect security misconfigurations and track compliance", + "waf": "Security" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Customers who are properly licensed to run Windows Virtual Desktop workloads are eligible to apply a Windows license to their session host virtual machines and run them without paying for another license.", - "guid": "7ba012e7-b94e-4f6e-847d-2ea2992b1cd6", - "link": "https://azure.microsoft.com/pricing/details/virtual-desktop/", - "severity": "Low", - "subcategory": "Clients & Users", - "text": "Check licensing requirements" + "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": [ + "Arc" + ], + "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": "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. ", - "guid": "d2f54b29-769e-43a6-a1e8-838ac936667e", - "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", - "severity": "High", - "subcategory": "Clients & Users", - "text": "Run a PoC to test end-to-end user experience to verify impact caused by network latency" + "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": [ + "AKS" + ], + "severity": "Medium", + "subcategory": "Development", + "text": "Use canary or blue/green deployments", + "waf": "Operations" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Determine if users will be offered full desktops and/or Remote Application Groups. ", - "guid": "13c00567-4b1e-4945-a459-837ee7ad6c6d", - "link": "https://learn.microsoft.com/azure/virtual-desktop/manage-app-groups", + "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": [ + "AKS" + ], "severity": "Low", - "subcategory": "Clients & Users", - "text": "Determine if users will access AVD using full desktops and/or remote applications " + "subcategory": "Development", + "text": "If required for AKS Windows workloads HostProcess containers can be used", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "RDP settings can currently only be configured at the host pool level, not per user / group.", - "guid": "3b365a5c-7acb-4e48-abe5-4cd79f2e8776", - "link": "https://learn.microsoft.com/azure/virtual-desktop/customize-rdp-properties", + "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": [ + "AKS" + ], "severity": "Low", - "subcategory": "Clients & Users", - "text": "All users will have the same RDP settings? " + "simple": -1, + "subcategory": "Development", + "text": "Use KEDA if running event-driven workloads", + "waf": "Performance" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "RDP Shortpath for managed networks is a feature of Azure Virtual Desktop that establishes a direct UDP-based transport between Remote Desktop Client and Session host. The removal of extra relay reduces the round-trip time, which improves user experience with latency-sensitive applications and input methods. To support RDP Shortpath, the Azure Virtual Desktop client needs a direct line of sight to the session host, and must be running either Windows 10 or Windows 7 and have the Windows Desktop client installed.", - "guid": "b2074747-d01a-4f61-b1aa-92ad793d9ff4", - "link": "https://learn.microsoft.com/azure/virtual-desktop/shortpath", + "category": "Application Deployment", + "checklist": "Azure AKS Review", + "guid": "26886d20-b66c-457b-a591-19bf8e8f5c58", + "id": "01.01.04", + "link": "https://dapr.io/", + "services": [ + "AKS" + ], + "severity": "Low", + "simple": 1, + "subcategory": "Development", + "text": "Use Dapr to ease microservice development", + "waf": "Operations" + }, + { + "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": [ + "AKS" + ], "severity": "Medium", - "subcategory": "Clients & Users", - "text": "Evaluate RDP ShortPath for clients connecting from managed internal networks" + "simple": -1, + "subcategory": "Infrastructure as Code", + "text": "Use automation through ARM/TF to create your Azure resources", + "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", - "link": "https://azure.microsoft.com/global-infrastructure/services/?products=virtual-desktop", + "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": [ + "ASR", + "AKS" + ], "severity": "High", - "subcategory": "General", - "text": "Determine in which Azure region/s AVD Host Pools will be deployed." + "subcategory": "Disaster Recovery", + "text": "Schedule and perform DR tests regularly", + "waf": "Reliability" }, { - "category": "Foundation", - "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. ", - "guid": "dd399cfd-7b28-4dc8-9555-6202bfe4563b", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "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": [ + "FrontDoor", + "AKS", + "TrafficManager", + "LoadBalancer" + ], "severity": "Medium", - "subcategory": "General", - "text": "Determine if hybrid connectivity is required to connect to on-premises environment" + "subcategory": "High Availability", + "text": "Use Azure Traffic Manager or Azure Front Door as a global load balancer for region failover", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "Run the 'Windows 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": "0d834a34-8b26-43e6-bc60-512a26498f6d", - "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", - "severity": "High", - "subcategory": "General", - "text": "Did you evaluate latency between users location and Azure AVD infrastructure?" + "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": "High Availability", + "text": "Use Availability Zones if they are supported in your Azure region", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD store metadata only to run the service in specific geographic locations, determine what is available today and if suitable based on customer requirements. ", - "guid": "bad37ead-53cc-47ce-8d7a-aab3571449ab", - "link": "https://learn.microsoft.com/azure/virtual-desktop/data-locations", - "severity": "Medium", - "subcategory": "General", - "text": "Determine metadata location for AVD service" + "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": "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 availability if used. ", - "guid": "8053d89e-89dc-47b3-9be2-a1a27f7a9e91", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "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": [ + "Cost", + "AKS" + ], "severity": "Low", - "subcategory": "General", - "text": "Check Azure quotas and availability for specific VM sizes in the selected regions" + "simple": -1, + "subcategory": "High Availability", + "text": "Use Disruption Budgets in your pod and deployment definitions", + "waf": "Reliability" }, { - "category": "Foundation", - "checklist": "Azure Virtual Desktop Review", - "description": "See BCDR section for more details.", - "guid": "be1f38ce-f398-412b-b463-cbbac89c199d", - "link": "https://learn.microsoft.com/azure/availability-zones/az-region", - "severity": "Medium", - "subcategory": "General", - "text": "Check for Availability Zone (AZ) availability in the selected region" + "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": [ + "ACR", + "AKS" + ], + "severity": "High", + "subcategory": "High Availability", + "text": "If using a private registry, configure region replication to store images in multiple regions", + "waf": "Reliability" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "AD DCs in Azure are recommended to reduce latency for users logging into AVD session hosts, and eventually for Azure NetApp Files and AD integration. ADC 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", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", - "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create at least two Active Directory Domain Controllers (DCs) in Azure VNET environment close to AVD Host Pool" + "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": [ + "AKS" + ], + "severity": "High", + "subcategory": "Requirements", + "text": "Define non-functional requirements such as SLAs, RTO (Recovery Time Objective) and RPO (Recovery Point Objective).", + "waf": "Reliability" }, { - "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", + "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": [ + "Cost", + "AKS" + ], "severity": "Low", - "subcategory": "Active Directory", - "text": "Create a specific OU in Active Directory for each Host Pool" + "subcategory": "Cost", + "text": "Use an external application such as kubecost to allocate costs to different users", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Carefully review, and eventually block/filter inheritance of GPOs to the OUs containing AVD Host Pools. ", - "guid": "7126504b-b47a-4393-a080-327294798b15", - "link": "https://learn.microsoft.com/previous-versions/windows/desktop/Policy/group-policy-hierarchy", - "severity": "Medium", - "subcategory": "Active Directory", - "text": "Review Domain GPO that will be applied to OU and impacting Host Pool VM functionalities" + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "64d1a846-e28a-4b6b-9a33-22a635c15a21", + "id": "03.01.02", + "link": "https://learn.microsoft.com/azure/aks/node-pool-snapshot", + "services": [ + "Cost", + "AKS" + ], + "severity": "Low", + "subcategory": "Cost", + "text": "If required scale NodePool snapshots", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Recommended to have a specific dedicated account with specific permissions, and without the default 10 joins limitation. ", - "guid": "347dc560-28a7-41ff-b1cd-15dd2f0d5e77", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", - "severity": "Medium", - "subcategory": "Active Directory", - "text": "Create a dedicated user account with only permissions to join VM to the domain" + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "4d3dfbab-9924-4831-a68d-fdf0d72f462c", + "id": "03.01.03", + "link": "https://learn.microsoft.com/azure/aks/scale-down-mode", + "services": [ + "Cost", + "AKS" + ], + "severity": "Low", + "subcategory": "Cost", + "text": "Use scale down mode to delete/delallocate nodes", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Avoid granting access per user, instead use AD groups and replicate them using ADC in Azure AD. ", - "guid": "2d41e361-1cc5-47b4-a4b1-410d43958a8c", - "link": "https://learn.microsoft.com/azure/virtual-desktop/manage-app-groups", + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "87e651ea-bc4a-4a87-a6df-c06a4b570ebc", + "id": "03.01.04", + "link": "https://learn.microsoft.com/azure/aks/gpu-multi-instance", + "services": [ + "Cost", + "AKS" + ], "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": "Cost", + "text": "When required use multi-instance partioning GPU on AKS Clusters", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "As part of the procedure to integrate Azure File Share and Active Directory authentication, 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", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-identity-ad-ds-enable", + "category": "Cost Governance", + "checklist": "Azure AKS Review", + "cost": 1, + "guid": "2b72a08b-0410-4cd6-9093-e068a5cf27e8", + "id": "03.01.05", + "link": "https://learn.microsoft.com/azure/aks/start-stop-nodepools", + "services": [ + "Cost", + "AKS" + ], "severity": "Low", - "subcategory": "Active Directory", - "text": "Review your organization password expiration policy for accounts used by Azure Files AD integration" + "subcategory": "Cost", + "text": "If running a Dev/Test cluster use NodePool Start/Stop", + "waf": "Cost" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "An Azure subscription must be parented to the same Azure AD tenant, that contains a virtual network that either contains or is connected to the Windows Server Active Directory or Azure AD DS instance.", - "guid": "6ceb5443-5125-4922-9442-93bb628537a5", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", - "severity": "High", - "subcategory": "Requirements", - "text": "An Azure Active Directory tenant must be available with at least one subscription linked" + "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": [ + "AzurePolicy", + "AKS" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Compliance", + "text": "Use Azure Policy for Kubernetes to ensure cluster compliance", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "You can configure this using Azure AD Connect (for hybrid organizations) or Azure AD Domain Services (for hybrid or cloud organizations).", - "guid": "5119bf8e-8f58-4542-a7d9-cec166cd072a", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", - "severity": "High", - "subcategory": "Requirements", - "text": "A Windows Server Active Directory forest/domain is in sync with Azure Active Directory" + "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": [ + "AKS" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Compliance", + "text": "Separate applications from the control plane with user/system nodepools", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "(1) The user must be sourced from the same Active Directory that's connected to Azure AD. Windows Virtual Desktop does not support B2B or MSA accounts. (2) The UPN you use to subscribe to Windows Virtual Desktop must exist in the Active Directory domain the VM is joined to.", - "guid": "f9b141a8-98a5-435e-9378-97e71ca7da7b", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", - "severity": "Medium", - "subcategory": "Requirements", - "text": "Check User Account requirements to connect to Windows Virtual Desktop" + "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": [ + "AKS" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Compliance", + "text": "Add taint to your system nodepool to make it dedicated", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "VMs must be Standard domain-joined or Hybrid AD-joined. Virtual machines can't be Azure AD-joined.", - "guid": "ea962a15-9394-46da-a7cc-3923266b2258", - "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", + "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": [ + "ACR", + "AKS" + ], "severity": "Medium", - "subcategory": "Requirements", - "text": "Check VM requirements for AVD Session Hosts that will be created" + "simple": -1, + "subcategory": "Compliance", + "text": "Use a private registry for your images, such as ACR", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure Virtual Desktop Review", - "description": "Compare self-managed Active Directory Domain Services, Azure Active Directory, and managed Azure Active Directory Domain Services", - "guid": "6f4a1651-bddd-4ea8-a487-cdeb4861bc3b", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/compare-identity-solutions", - "severity": "Low", - "subcategory": "Requirements", - "text": "Before using Azure Active Directory Domain Services (AAD-DS) for AVD, be sure to review the limitations. " + "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": [ + "AKS" + ], + "severity": "Medium", + "subcategory": "Compliance", + "text": "Scan your images for vulnerabilities", + "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, recommended to have a separate setup for each host pool. ", - "guid": "7138b820-102c-4e16-be30-1e6e872e52e3", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-scaling-script", - "severity": "Low", - "subcategory": "Management", - "text": "Assess the requirement for host pool auto-scaling capability" + "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": [ + "Defender", + "AKS" + ], + "severity": "Medium", + "subcategory": "Compliance", + "text": "Use Azure Security Center to detect security posture vulnerabilities", + "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-advisor", + "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": [ + "AKS" + ], "severity": "Low", - "subcategory": "Management", - "text": "Periodically check Azure Advisor recommendations for AVD" + "subcategory": "Compliance", + "text": "If required configure FIPS", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Prepare a strategy to manage updates to golden images, for example to apply security hotfixes and/or update applications installed inside the image. Azure Image Builder Service is a 1st party solution for automating the build and customization of VMs. ARM templates can be used to create new hosts, then decommission the old ones: https://github.com/Azure/RDS-Templates/tree/master/ARM-AVD-templates/AddVirtualMachinesToHostPool Recommended approach is to create a new pool side-by-side, easier to rollback, not usable for dedicated poolRe-deploy and increase the number of VMs with the ARM template is also a viable option. Customers may also want to use existing software distribution methods to update image without re-deploy, for example with SCCM or similar.", - "guid": "d7b68d0c-7555-462f-8b3e-4563b4d874a7", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/image-builder-virtual-desktop", - "severity": "Medium", - "subcategory": "Management", - "text": "Plan for a golden image update management strategy" + "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": [ + "AKS" + ], + "severity": "High", + "subcategory": "Compliance", + "text": "Define app separation requirements (namespace/nodepool/cluster)", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Customers can have several options:- Microsoft Endpoint Configuration Manager, this article explains how to configure Microsoft Endpoint Configuration Manager to automatically apply updates to a Windows Virtual Desktop host running Windows 10 Enterprise multi-session: https://learn.microsoft.com/azure/virtual-desktop/configure-automatic-updates- Microsoft Intune: https://learn.microsoft.com/mem/intune/fundamentals/windows-virtual-desktop-multi-session- Windows Server Update Services (WSUS)- 3rd Party that supports you OS.- Azure Update Management (Azure Automation), today not supported for client OS: https://learn.microsoft.com/azure/automation/update-management/overview#unsupported-operating-systemsIt is recommended to move away from a patching strategy and move to a re-imaging strategy if possible. ", - "guid": "04722da2-9c2b-41cd-922f-54b29bade3aa", - "link": "https://learn.microsoft.com/azure/virtual-machines/windows/image-builder-virtual-desktop", + "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": [ + "AKS", + "AKV" + ], "severity": "Medium", - "subcategory": "Management", - "text": "Plan for a Session Host patching and update strategy" - }, - { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Host pools are a collection of one or more identical virtual machines within Windows 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/create-validation-host-pool", - "severity": "Low", - "subcategory": "Management", - "text": "Assess the requirement for a AVD test canary environment" + "simple": -1, + "subcategory": "Secrets", + "text": "Store your secrets in Azure Key Vault with the CSI Secrets Store driver", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "A AVD Host Pool can be deployed in several ways: Azure Portal, ARM templates, Azure CLI tool, Powershell, manual VM creation with registration token, Terraform, etc. It is important to adopt proper method/s to support automatic deployment through automation and CI/CD tools.", - "guid": "a459c373-e7ed-4616-83b3-65a917ecbe48", - "link": "https://github.com/Azure/RDS-Templates/tree/master/AVD-templates", - "severity": "Medium", - "subcategory": "Management", - "text": "Determine Host Pool deployment strategy" + "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": [ + "AKS", + "AKV" + ], + "severity": "High", + "subcategory": "Secrets", + "text": "If using Service Principals for the cluster, refresh credentials periodically (like quarterly)", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "After you register a VM to a host pool within the Windows 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/faq", + "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": [ + "AKS", + "AKV" + ], "severity": "Medium", - "subcategory": "Management", - "text": "Turn on VMs regularly every 90 days for token refresh" + "subcategory": "Secrets", + "text": "If required add Key Management Service etcd encryption", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure Monitor for Windows Virtual Desktop is a dashboard built on Azure Monitor Workbooks that helps IT professionals understand their Windows Virtual Desktop environments. Read the referenced article to learn how to set up Azure Monitor for Windows Virtual Desktop to monitor your Windows Virtual Desktop environments.", - "guid": "63cfff1c-ac59-49ef-8d5a-83dd4de36c1c", - "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-monitor", - "severity": "High", - "subcategory": "Monitoring", - "text": "Enable Azure Monitoring for AVD" + "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": [ + "AKS", + "AKV" + ], + "severity": "Low", + "subcategory": "Secrets", + "text": "If required consider using Confidential Compute for AKS", + "waf": "Security" }, { - "category": "Monitoring and Management", - "checklist": "Azure Virtual Desktop Review", - "description": "Windows 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics", + "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", + "AKV" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable and redirect diagnostic settings for Workspaces, Host Pools, Application Groups and Host VMs to Log Analytics workspace" + "subcategory": "Secrets", + "text": "Consider using Defender for Containers", + "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://learn.microsoft.com/azure/storage/files/storage-troubleshooting-files-performance. ", - "guid": "2463cffe-179c-4599-be0d-5973dd4ce32c", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-monitoring?tabs=azure-portal", - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Create alerts on the profile storage to be alerted in case of high usage and throttling" + "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": [ + "AKS", + "Entra" + ], + "severity": "High", + "simple": 1, + "subcategory": "Identity", + "text": "Use managed identities instead of Service Principals", + "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 Windows 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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-service-alerts", + "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": [ + "AKS", + "Entra" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Configure Azure Service Health for AVD alerts " + "simple": 1, + "subcategory": "Identity", + "text": "Integrate authentication with AAD (using the managed integration)", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Which type of hybrid connectivity? Express Route, VPN, NVA?", - "guid": "c8639648-a652-4d6c-85e5-02965388e5de", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "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": [ + "AKS", + "Entra" + ], "severity": "Medium", - "subcategory": "Networking", - "text": "Review hybrid connectivity architecture for on-premises environment" + "simple": -1, + "subcategory": "Identity", + "text": "Limit access to admin kubeconfig (get-credentials --admin)", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Evaluate the bandwidth requirements, ensure VPN/ER bandwidth will be enough, and latency tolerable. ", - "guid": "d227dd14-2b06-4c21-a799-9a646f4389a7", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "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": [ + "AKS", + "Entra", + "RBAC" + ], "severity": "Medium", - "subcategory": "Networking", - "text": "Assess which resources users will need to access from AVD Host Pools to on-premises" + "simple": -1, + "subcategory": "Identity", + "text": "Integrate authorization with AAD RBAC", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Review or recommend a new one where to place AVD Host Pools based on CAF (vWAN vs. Hub & Spoke)", - "guid": "f42c78e7-8c06-4a63-a21a-4956e6a8dc4a", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/networking-options", + "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": [ + "AKS", + "Entra", + "RBAC" + ], "severity": "High", - "subcategory": "Networking", - "text": "Review landing zone networking topology for AVD service" + "simple": -1, + "subcategory": "Identity", + "text": "Use namespaces for restricting RBAC privilege in Kubernetes", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Ensure each subnet will have enough space to scale the AVD Host Pool. For different Host Pools, it is recommended to use separate subnets if possible. ", - "guid": "20e27b3e-2971-41b1-952b-eee079b588de", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", + "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": [ + "AKS", + "Entra" + ], "severity": "Medium", - "subcategory": "Networking", - "text": "Assess VNET and subnet placement for multiple Host Pools" + "simple": -1, + "subcategory": "Identity", + "text": "For POD Identity Access Management use Azure AD Workload Identity (preview)", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Several options are available. You can use Azure Firewall or NVA Firewall, NSG and/or Proxy. 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 here on https://aka.ms/AVDfirewall and here https://learn.microsoft.com/azure/firewall/protect-windows-virtual-desktop. Be sure to review full list of requirements for AVD URLs access.", - "guid": "fc4972cd-3cd2-41bf-9703-6e5e6b4bed3d", - "link": "https://aka.ms/AVDfirewall", + "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": [ + "AKS", + "Entra" + ], "severity": "Medium", - "subcategory": "Networking", - "text": "Need to control/restrict Internet outbound traffic for AVD hosts? " + "simple": -1, + "subcategory": "Identity", + "text": "For AKS non-interactive logins use kubelogin (preview)", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Consider the usage of Azure Defender Endpoint to control user web navigation, see the Security section for more details. ", - "guid": "73676ae4-6691-4e88-95ad-a42223e13810", - "link": "https://techcommunity.microsoft.com/t5/microsoft-defender-for-endpoint/windows-virtual-desktop-support-is-now-generally-available/ba-p/2103712", + "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": [ + "AKS", + "Entra" + ], "severity": "Medium", - "subcategory": "Networking", - "text": "Need to control/restrict Internet outbound traffic only for users on AVD hosts? " + "simple": -1, + "subcategory": "Identity", + "text": "Disable AKS local accounts", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Custom UDR can be applied to AVD Host Pool subnet, for example to redirect to Azure Firewall or NVA. 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, then AVD management plane traffic can be easily whitelisted. https://learn.microsoft.com/azure/firewall/protect-windows-virtual-desktop#host-pool-outbound-access-to-windows-virtual-desktop ", - "guid": "523181a9-4174-4158-93ff-7ae7c6d37431", - "link": "https://learn.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "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": [ + "AKS", + "Entra" + ], "severity": "Low", - "subcategory": "Networking", - "text": "Review UDR for AVD Host Pool subnet" - }, - { - "category": "Networking", - "checklist": "Azure Virtual Desktop Review", - "description": "Required URLs for AVD control plane access by session hosts are documented here: https://learn.microsoft.com/azure/virtual-desktop/safe-url-list. A check tool is available to verify connectivity from the session hosts: https://learn.microsoft.com/azure/virtual-desktop/safe-url-list#required-url-check-tool.", - "guid": "65c7acbe-45bb-4e60-ad89-f2e87778424d", - "link": "https://learn.microsoft.com/azure/virtual-desktop/safe-url-list", - "severity": "High", - "subcategory": "Networking", - "text": "Ensure AVD control plane endpoints are accessible" + "simple": -1, + "subcategory": "Identity", + "text": "Configure if required Just-in-time cluster access", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/network-guidance", - "severity": "Low", - "subcategory": "Networking", - "text": "Check the network bandwidth required for each user and in total for the VM SKU" + "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": [ + "AKS", + "Entra" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Identity", + "text": "Configure if required AAD conditional access for AKS", + "waf": "Security" }, { - "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 like Microsoft Endpoint Manager. In a multi-session environment, we recommend you don't let users install software directly.", - "guid": "a0cdb3b5-4eb2-4eb0-9dda-a3592718e2ed", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", + "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": [ + "AKS", + "Entra" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Identity", + "text": "If required for Windows AKS workloads configure gMSA ", + "waf": "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": [ + "AKS", + "Entra" + ], "severity": "Medium", - "subcategory": "Host Configuration", - "text": "Ensure AVD users will not have local admin privileges on AVD Hosts. " + "simple": -1, + "subcategory": "Identity", + "text": "For finer control consider using a managed Kubelet Identity", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Microsoft Defender for Endpoint now supports Windows Virtual Desktop for Windows 10 Enterprise multi-session.Check article for onboarding non-persistent virtual desktop infrastructure (VDI) devices: https://learn.microsoft.com/windows/security/threat-protection/microsoft-defender-atp/configure-endpoints-vdi", - "guid": "b1172576-9ef6-4691-a483-5ac932223ece", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", - "severity": "High", - "subcategory": "Host Configuration", - "text": "Ensure anti-virus and anti-malware solution is used" + "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": [ + "AppGW", + "AKS", + "ACR" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Best practices", + "text": "If using AGIC, do not share an AppGW across clusters", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Be sure the following exclusions are in place: https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix#antivirus-exclusions .", - "guid": "80b12308-1a54-4174-8583-3ea3ad2c2de7", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", + "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": [ + "AKS" + ], "severity": "High", - "subcategory": "Host Configuration", - "text": "Ensure proper AV exclusions are in place" + "simple": -1, + "subcategory": "Best practices", + "text": "Do not use AKS Application Routing Add-On", + "waf": "Reliability" }, { - "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 ADE and DES: sensible and persistent user data should not be stored on the Session Host disk, then it should be used only if strictly required for compliance reason. Encryption of FSLogix storage using Azure Files can be done using SSE on Azure Storage.For OneDrive encryption, see this article: https://learn.microsoft.com/compliance/assurance/assurance-encryption-for-microsoft-365-services.", - "guid": "0fd32907-98bc-4178-adc5-a06ca7144351", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", - "severity": "Low", - "subcategory": "Host Configuration", - "text": "Assess disk encryption requirements for AVD Hosts" + "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": [ + "AKS" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Best practices", + "text": "For Windows workloads use Accelerated Networking", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Consider the usage of Azure Defender Endpoint to control user web navigation. ", - "guid": "e19dd344-29eb-4722-a237-a151c5bb4e4f", - "link": "https://techcommunity.microsoft.com/t5/microsoft-defender-for-endpoint/windows-virtual-desktop-support-is-now-generally-available/ba-p/2103712", - "severity": "Medium", - "subcategory": "Host Configuration", - "text": "Need to control/restrict user Internet navigation from AVD session hosts?" + "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": [ + "AKS", + "LoadBalancer" + ], + "severity": "High", + "subcategory": "Best practices", + "text": "Use the standard ALB (as opposed to the basic one)", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "We recommend you enable Azure Security Center Standard for subscriptions, virtual machines, key vaults, and storage accounts.With Azure Security Center Standard is possible to assess and manage vulnerabilities, assess compliance with common frameworks like PCI, strengthen the overall security of your AVD environment.", - "guid": "1814387e-5ca9-4c26-a9b3-2ab5bdfc6998", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", + "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": [ + "VNet", + "AKS" + ], "severity": "Medium", - "subcategory": "Security", - "text": "Evaluate the usage of Azure Security Center (ASC) for AVD Session Hosts" + "simple": -2, + "subcategory": "Best practices", + "text": "If using Azure CNI, consider using different Subnets for NodePools", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Should be used, for example to impose desktop lockout and idle session termination. Existing GPOs applied to on-premises environment should be reviewed and eventually applied to secure also AVD Hosts. ", - "guid": "a135e337-897e-431c-97d6-8cb6a22ac19f", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", + "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": [ + "PrivateLink", + "VNet", + "AKS", + "Cost" + ], "severity": "Medium", - "subcategory": "Security", - "text": "Review Active Directory GPOs to secure RDP sessions" + "simple": -1, + "subcategory": "Cost", + "text": "Use Private Endpoints (preferred) or Virtual Network Service Endpoints to access PaaS services from the cluster", + "waf": "Security" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "For additional details and insights, see this article: https://christiaanbrinkhoff.com/2020/03/23/learn-how-to-increase-the-security-level-of-your-windows-virtual-desktop-environment-e-g-windows-client-with-azure-mfa-and-conditional-access", - "guid": "916d697d-8ead-4ed2-9bdd-186f1ac252b9", - "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-mfa", - "severity": "Low", - "subcategory": "Security", - "text": "Evaluate the usage of MFA for AVD users" + "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": [ + "VPN", + "AKS" + ], + "severity": "Medium", + "subcategory": "HA", + "text": "If hybrid connectivity is required, use 2xER or ER+VPN for better availability", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Enabling Conditional Access lets you manage risks before you grant users access to your Windows Virtual Desktop 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.", - "guid": "556246b4-3856-44b4-bc74-a748b6633ad2", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", - "severity": "Low", - "subcategory": "Security", - "text": "Evaluate the usage of Conditional Access for users" + "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": [ + "AKS" + ], + "severity": "High", + "simple": 1, + "subcategory": "IPAM", + "text": "Choose the best CNI network plugin for your requirements (Azure CNI recommended)", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "Enabling audit log collection lets you view user and admin activity related to Windows Virtual Desktop. This is also a requirement to enable and use AVD Monitoring tool. Highly recommended to enable. ", - "guid": "a0916a76-4980-4ad0-b278-ee293c1bc352", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", - "severity": "Medium", - "subcategory": "Security", - "text": "Enable diagnostic and audit logging to central Log Analytics workspace" + "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": [ + "VNet", + "AKS" + ], + "severity": "High", + "subcategory": "IPAM", + "text": "If using Azure CNI, size your subnet accordingly considering the maximum number of pods per node", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "AVD uses Azure role-based access controls (RBAC) to assign roles to users and admins. These roles give admins permission to carry out certain tasks. If separation of duties is required, Windows Virtual Desktop has additional roles that let you separate management roles for host pools, app groups, and workspaces. This separation lets you have more granular control over administrative tasks. These roles are named in compliance with Azure's standard roles and least-privilege methodology.", - "guid": "baaab757-1849-4ab8-893d-c9fc9d1bb73b", - "link": "https://learn.microsoft.com/azure/virtual-desktop/rbac", - "severity": "Low", - "subcategory": "Security", - "text": "Assess the requirement to use custom RBAC roles for AVD management " + "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": [ + "AKS" + ], + "severity": "High", + "simple": -1, + "subcategory": "IPAM", + "text": "If using Azure CNI, check the maximum pods/node (default 30)", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Azure Virtual Desktop Review", - "description": "A comprehensive set of security best practices and recommendations are contained in the referenced article, it is recommended to review. ", - "guid": "36a5a67f-bb9e-4d5b-9547-8c4479816b28", - "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide", - "severity": "Medium", - "subcategory": "Security", - "text": "Review all security best practices for AVD environment" + "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": [ + "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" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Azure NetApp Files, Azure Files, VM based File Server. File-server not recommended. Azure Files Premium typically a good starting point. NetApp only usually required for large scale / high-performant environment. ", - "guid": "ed6b17db-8255-4462-b2ae-e4553afc8339", - "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "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": [ + "AKS" + ], "severity": "High", - "subcategory": "FSLogix", - "text": "Determine which storage backend solution will be used for FSLogix Profile and Office Containers" + "subcategory": "IPAM", + "text": "Size the service IP address range accordingly (it is going to limit the cluster scalability)", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "The recommendation in Windows Virtual Desktop is to use Profile Container without Office Container unless you are planning for specific Business Continuity and Disaster Recovery (BCDR) scenarios as described in the Disaster Recovery section below. https://learn.microsoft.com/fslogix/profile-container-office-container-cncpt ", - "guid": "df47d2d9-2881-4b1c-b5d1-e54a29759e39", - "link": "https://learn.microsoft.com/fslogix/profile-container-office-container-cncpt", + "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": [ + "AKS" + ], "severity": "Low", - "subcategory": "FSLogix", - "text": "Evaluate the possibility to separate Profile Containers from Office Containers" + "simple": -2, + "subcategory": "Operations", + "text": "If required add your own CNI plugin", + "waf": "Security" }, { - "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.", - "guid": "680e7828-9c93-4665-9d02-bff4564b0d93", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", - "severity": "High", - "subcategory": "FSLogix", - "text": "Verify storage scalability limits to support Host Pool requirements" + "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": [ + "AKS" + ], + "severity": "Low", + "simple": -2, + "subcategory": "Operations", + "text": "If required configure Public IP per node in AKS", + "waf": "Performance" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "If a second region is required for DR purposes verify NetApp availability there as well.", - "guid": "4a359836-ee79-4d6c-9d3a-364a5b7abae3", - "link": "https://azure.microsoft.com/global-infrastructure/services/", + "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": [ + "AKS" + ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "If NetApp Files storage is used, check storage service availability in your specific region." + "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": "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", - "link": "https://learn.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files", - "severity": "High", - "subcategory": "FSLogix", - "text": "For optimal performance, the storage solution and the FSLogix profile container should be in the same data-center location." + "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": [ + "AKS" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Scalability", + "text": "Use Azure NAT Gateway as outboundType for scaling egress traffic", + "waf": "Reliability" }, { - "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.", - "guid": "83f63047-22ee-479d-9b5c-3632054b69ba", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", + "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": [ + "AKS" + ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "Configure the recommended antivirus exclusions for FSLogix (includes not scanning VHD(x) files on connect)." + "simple": -1, + "subcategory": "Scalability", + "text": "Use Dynamic allocations of IPs in order to avoid Azure CNI IP exhaustion", + "waf": "Reliability" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Default basic and recommended settings are here: https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix#best-practice-settings-for-enterprises See here for core set: https://learn.microsoft.com/fslogix/configure-profile-container-tutorialSee here for complete reference: https://learn.microsoft.com/fslogix/profile-container-configuration-reference ", - "guid": "d34aad5e-8c78-4e1d-9666-7313c405674c", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", + "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": [ + "AKS", + "NVA" + ], "severity": "High", - "subcategory": "FSLogix", - "text": "Review FSLogix registry keys and determine which ones to apply" + "simple": -2, + "subcategory": "Security", + "text": "Filter egress traffic with AzFW/NVA if your security requirements mandate it", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Concurrent or multiple connections are discouraged in Windows Virtual Desktop. The best practice is to create a different profile location for each session (as a host pool).", - "guid": "5e985b85-9c77-43e7-b261-623b775a917e", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", - "severity": "High", - "subcategory": "FSLogix", - "text": "Check usage of concurrent or multiple connections to the same profile" - }, - { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "As a general estimation, to be validated in a test environment, for each user 5 - 15 IOPS should be first considered, depending on the workload. Azure Files: Premium max 100k IOPS per share (max 100TB) and up to 5Gbps with 3ms latency. Be aware of how Azure Files is provisioned, that is IOPS strictly tied t'o provisioned SIZE. Burst sizing capability in some cases. Be sure to provision UPFRONT more space than required to be sure to have enough IOPS. NOTE: Azure Premium maybe cheaper than Standard because you don't pay transactions, then important detail to keep in mind.Azure NetApp Files: remember max 1000 IPs connected, can adjust IOPS on the fly, minimum 4TB provisioned capacity. ", - "guid": "1f348ff3-64d2-47d4-8e8b-bbc868155abb", - "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", - "severity": "High", - "subcategory": "FSLogix", - "text": "Review best practices and key considerations for storage sizing" - }, - { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Make sure to check the list of best practices and recommendations described in the referenced article.", - "guid": "9164e990-9ae2-48c8-9c33-b6b7808bafe6", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", - "severity": "Medium", - "subcategory": "FSLogix", - "text": "Check best-practices for Azure Files (if used)" - }, - { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Make sure to check the list of best practices and recommendations described in the referenced article.", - "guid": "c42149d4-13a9-423c-9574-d11028ac6aae", - "link": "https://learn.microsoft.com/azure/architecture/example-scenario/AVD/windows-virtual-desktop-fslogix", + "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": [ + "AKS" + ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "Check best-practices for NetApp Files (if used)" + "simple": -1, + "subcategory": "Security", + "text": "If using a public API endpoint, restrict the IP addresses that can access it", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/fslogix/profile-container-configuration-reference", + "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": [ + "AKS" + ], "severity": "High", - "subcategory": "FSLogix", - "text": "Review and confirm configured maximum profile size in FSLogix" - }, - { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "Cloud Cache uses local disk as cache and may generate lot of pressure on the VM disk. Recommended to leverage the power of temporary (and locally attached) VM disk, if possible based on the VM SKU. ", - "guid": "b2d1215a-e114-4ba3-9df5-85ecdcd9bd3b", - "link": "https://learn.microsoft.com/fslogix/cloud-cache-configuration-reference", - "severity": "Medium", - "subcategory": "FSLogix", - "text": "If FSLogix Cloud Cache is used, move the Cache directory to temporary drive." + "simple": -1, + "subcategory": "Security", + "text": "Use private clusters if your requirements mandate it", + "waf": "Security" }, { - "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", - "link": "https://learn.microsoft.com/fslogix/manage-profile-content-cncpt#redirectionsxml", + "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": [ + "AzurePolicy", + "AKS" + ], "severity": "Medium", - "subcategory": "FSLogix", - "text": "Review the usage of FSLogix redirection." + "simple": -1, + "subcategory": "Security", + "text": "For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used ", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "An Active Directory Site should be created for the Azure virtual network environment where 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", - "link": "https://learn.microsoft.com/azure/azure-netapp-files/create-active-directory-connections", + "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": [ + "AzurePolicy", + "AKS" + ], "severity": "High", - "subcategory": "FSLogix", - "text": "If Azure NetApp Files storage is used, check AD Site name setting in the AD Connection." - }, - { - "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", - "link": "https://learn.microsoft.com/azure/storage/files/storage-files-smb-multichannel-performance", - "severity": "Medium", - "subcategory": "FSLogix", - "text": "Enable SMB multichannel when using a premium file share to host FSLogix profile containers." + "subcategory": "Security", + "text": "Enable a Kubernetes Network Policy option (Calico/Azure)", + "waf": "Security" }, { - "category": "Storage", - "checklist": "Azure Virtual Desktop Review", - "description": "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 you are going to use Cloud Cache. ", - "guid": "3611c818-b0a0-4bc5-80e4-3a18a9cd289c", - "link": "https://learn.microsoft.com/azure/virtual-machines/disks-types", - "severity": "Medium", - "subcategory": "Session Host ", - "text": "Determine which type of managed disk will be used for the Session Hosts " + "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": [ + "AzurePolicy", + "AKS" + ], + "severity": "High", + "simple": -1, + "subcategory": "Security", + "text": "Use Kubernetes network policies to increase intra-cluster security", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "32e42e36-11c8-418b-8a0b-c510e43a18a9", + "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": [ + "AKS", + "WAF" + ], "severity": "High", - "subcategory": "Identity", - "text": "Ensure ADDS domain controller(s) are deployed in the identity subscription in native Azure" + "simple": -1, + "subcategory": "Security", + "text": "Use a WAF for web workloads (UIs or APIs)", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "43f63047-22d9-429c-8b1c-d622f54b29ba", + "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", + "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": "Security", + "text": "Use DDoS Standard in the AKS Virtual Network", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "de3aad1e-7c28-4ec9-9666-b7570449aa80", - "severity": "High", - "subcategory": "Identity", - "text": "Ensure that vCenter is connected to ADDS to enable authentication based on 'named user accounts'" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Security", + "text": "If required add company HTTP Proxy", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "cd289ced-6b17-4db8-8554-61e2aee3553a", + "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": [ + "AKS" + ], "severity": "Medium", - "subcategory": "Identity", - "text": "Ensure that the connection from vCenter to ADDS is using a secure protocol (LDAPS)" + "simple": -2, + "subcategory": "Security", + "text": "Consider using a service mesh for advanced microservice communication management", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "b9d37dac-43bc-46cd-8d79-a9b24604489a", - "severity": "Medium", - "subcategory": "Identity", - "text": "CloudAdmin account in vCenter IdP is used only as an emergency account (break-glass)" + "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": [ + "Monitor", + "AKS" + ], + "severity": "High", + "simple": -1, + "subcategory": "Alerting", + "text": "Configure alerts on the most critical metrics (see Container Insights for recommendations)", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "53d88e89-d17b-473b-82a5-a67e7a9ed5b3", - "severity": "High", - "subcategory": "Identity", - "text": "Ensure that NSX-Manager is not integrated with external IdP as this is NOT supported at the moment (even though technically possible)" + "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": [ + "AKS", + "Entra" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Compliance", + "text": "Check regularly Azure Advisor for recommendations on your cluster", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "ae0e37ce-e297-411b-b352-caaab79b198d", - "severity": "Medium", - "subcategory": "Identity", - "text": "Has an RBAC model been created for use within VMware vSphere" + "category": "Operations", + "checklist": "Azure AKS Review", + "guid": "5388e9de-d167-4dd1-a2b0-ac241b999a64", + "id": "07.02.02", + "link": "https://learn.microsoft.com/azure/aks/operator-best-practices-scheduler", + "services": [ + "AKS" + ], + "severity": "Low", + "simple": 1, + "subcategory": "Compliance", + "text": "Develop your YAML manifests with intelligent text editors such as vscode+kubeadvisor", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "ab81932c-9fc9-4d1b-a780-36f5e6bfbb9e", - "severity": "Medium", - "subcategory": "Identity", - "text": "RBAC permissions should be granted on ADDS groups and not on specific users" + "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": [ + "AKS" + ], + "severity": "Low", + "simple": 1, + "subcategory": "Compliance", + "text": "Enable AKS auto-certificate rotation", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure VMware Solution Review", - "guid": "d503547c-c447-4e82-9128-a71f0f1cac6d", + "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": [ + "AKS" + ], "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" + "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": "Networking", - "checklist": "Azure VMware Solution Review", - "guid": "9ef1d5e8-32e4-42e3-911c-818b0a0bc510", - "link": "https://github.com/Azure/AzureCAT-AVS/tree/main/networking", + "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": [ + "AKS" + ], "severity": "High", - "subcategory": "Architecture", - "text": "Is the correct Azure VMware Solution connectivity model selected for the customer use case at hand" + "simple": -1, + "subcategory": "Compliance", + "text": "Use kured for Linux node upgrades in case you are not using node-image upgrade", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Review", - "guid": "dbf590ce-65de-48e0-9f9c-cbd468266abc", + "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": [ + "AKS" + ], "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure ExpressRoute or VPN connections from on-premises to Azure are monitored using 'connection monitor'" + "simple": -1, + "subcategory": "Compliance", + "text": "Have a regular process to upgrade the cluster node images periodically (weekly, for example)", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Review", - "guid": "e6a84de5-df43-4d19-a248-1718d5d1e5f6", - "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" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Compliance", + "text": "Consider gitops to deploy applications or cluster configuration to multiple clusters", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Review", - "guid": "25659d35-58fd-4772-99c9-31112d027fe4", - "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" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Compliance", + "text": "Consider using AKS command invoke on private clusters", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure VMware Solution Review", - "guid": "563b4dc7-4a74-48b6-933a-d1a0916a6649", - "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" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Compliance", + "text": "For planned events consider using Node Auto Drain", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "6128a71f-0f1c-4ac6-b9ef-1d5e832e42e3", + "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": [ + "AKS" + ], "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)" + "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": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "c4e2436b-b336-4d71-9f17-960eee0b9b5c", - "severity": "High", - "subcategory": "Security (identity)", - "text": "Is Privileged Identity Management audit reporting implemented for the Azure VMware Solution PIM roles" + "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": [ + "AKS" + ], + "severity": "Low", + "simple": 1, + "subcategory": "Compliance", + "text": "Use custom Node RG (aka 'Infra RG') name", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "8defc4d7-21d3-41d2-90fb-707ae9eab40e", - "severity": "High", - "subcategory": "Security (identity)", - "text": "Limit use of CloudAdmin account to emergency access only" + "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": [ + "AKS" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Compliance", + "text": "Do not use deprecated Kubernetes APIs in your YAML manifests", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "d329f798-bc17-48bd-a5a0-6ca7144351d1", - "severity": "Medium", - "subcategory": "Security (identity)", - "text": "Create custom RBAC roles in vCenter to implement a least-privilege model inside vCenter" + "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": [ + "AKS" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Compliance", + "text": "Taint Windows nodes", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "9dd24429-eb72-4281-97a1-51c5bb4e4f18", - "severity": "Medium", - "subcategory": "Security (identity)", - "text": "Is a process defined to regularly rotate cloudadmin (vCenter) and admin (NSX) credentials" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Compliance", + "text": "Keep windows containers patch level in sync with host patch level", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "586cb291-ec16-4a1d-876e-f9f141acdce5", - "severity": "High", - "subcategory": "Security (identity)", - "text": "Use a centralized identity provider to be used for workloads (VM's) running on Azure VMware Solution" + "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": [ + "Monitor", + "AKS" + ], + "severity": "Low", + "subcategory": "Compliance", + "text": "Send master logs (aka API logs) to Azure Monitor or your preferred log management solution", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "79377bcd-b375-41ab-8ab0-ead66e15d3d4", - "severity": "Medium", - "subcategory": "Security (network)", - "text": "Is East-West traffic filtering implemented within NSX-T" + "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": [ + "Cost", + "AKS" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Cost", + "text": "Consider spot node pools for non time-sensitive workloads", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "a2adb1c3-d232-46af-825c-a44e1695fddd", + "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": [ + "Cost", + "AKS" + ], + "severity": "Low", + "simple": -1, + "subcategory": "Cost", + "text": "Consider AKS virtual node for quick bursting", + "waf": "Operations" + }, + { + "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": [ + "Monitor", + "AKS" + ], "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" + "simple": -1, + "subcategory": "Monitoring", + "text": "Monitor your cluster metrics with Container Insights (or other tools like Prometheus)", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "eace4cb1-deb4-4c65-8c3f-c14eeab36938", + "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": [ + "Monitor", + "AKS" + ], "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" + "simple": -1, + "subcategory": "Monitoring", + "text": "Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch)", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "29e3eec2-1836-487a-8077-a2b5945bda43", + "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": [ + "Monitor", + "AKS" + ], "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" + "simple": -1, + "subcategory": "Monitoring", + "text": "Monitor CPU and memory utilization of the nodes", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "334fdf91-c234-4182-a652-75269440b4be", + "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": [ + "Monitor", + "AKS" + ], "severity": "Medium", - "subcategory": "Security (network)", - "text": "Is DDoS standard protection enabled on ExR/VPN Gateway subnet in Azure" + "simple": -1, + "subcategory": "Monitoring", + "text": "If using Azure CNI, monitor % of pod IPs consumed per node", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "3d3e0843-276d-44bd-a015-bcf219e4a1eb", + "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": [ + "ServiceBus", + "EventHubs", + "Monitor", + "AKS", + "Storage" + ], "severity": "Medium", - "subcategory": "Security (network)", - "text": "Use a dedicated privileged access workstation (PAW) to manage Azure VMware Solution, vCenter, NSX manager and HCX manager" + "simple": -1, + "subcategory": "Monitoring", + "text": "Monitor OS disk queue depth in nodes", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "9ccbd869-266a-4cca-874f-aa19bf39d95d", + "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": [ + "Monitor", + "AKS", + "NVA", + "LoadBalancer" + ], "severity": "Medium", - "subcategory": "Security (guest/VM)", - "text": "Enable Advanced Threat Detection (MDfC aka ASC) for workloads running on Azure VMware Solution" + "simple": -1, + "subcategory": "Monitoring", + "text": "If not using egress filtering with AzFW/NVA, monitor standard ALB allocated SNAT ports", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "44c7c891-9ca1-4f6d-9315-ae524ba34d45", + "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": [ + "Monitor", + "AKS" + ], "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)" + "subcategory": "Monitoring", + "text": "Subscribe to resource health notifications for your AKS cluster", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "85e12139-bd7b-4b01-8f7b-95ef6e043e2a", - "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)" + "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": [ + "AKS" + ], + "severity": "High", + "simple": -1, + "subcategory": "Resources", + "text": "Configure requests and limits in your pod specs", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "a3592718-e6e2-4051-9267-6ae46691e883", - "severity": "Low", - "subcategory": "Security (guest/VM)", - "text": "When in-guest encryption is used, store encryption keys in Azure Key vault when possible" + "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": [ + "AKS" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Resources", + "text": "Enforce resource quotas for namespaces", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "5ac94222-3e13-4810-9230-81a941741583", + "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": [ + "Subscriptions", + "AKS" + ], "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)" + "subcategory": "Resources", + "text": "Ensure your subscription has enough quota to scale out your nodepools", + "waf": "Operations" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "3ef7ad7c-6d37-4331-95c7-acbe44bbe609", - "severity": "High", - "subcategory": "Governance (platform)", - "text": "Ensure that the appropriate VM template storage policy is used" + "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": [ + "AKS" + ], + "severity": "Medium", + "subcategory": "Scalability", + "text": "Use the Cluster Autoscaler", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "d89f2e87-7784-424d-9167-85c6fa95b96a", + "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": [ + "AKS" + ], "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Ensure that you have requested enough quota, ensuring you have considered growth and Disaster Recovery requirement" + "subcategory": "Scalability", + "text": "Customize node configuration for AKS node pools", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "d88408f3-7273-44c8-96ba-280214590146", - "severity": "High", - "subcategory": "Governance (platform)", - "text": "Ensure that the Failure-to-tolerate policy is in place to meet your vSAN storage needs" + "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": [ + "AKS" + ], + "severity": "Medium", + "simple": -1, + "subcategory": "Scalability", + "text": "Use the Horizontal Pod Autoscaler when required", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "5d38e53f-9ccb-4d86-a266-acca274faa19", - "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Ensure that access constraints to ESXi are understood, there are access limits which might affect 3rd party solutions." + "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": [ + "AKS" + ], + "severity": "High", + "subcategory": "Scalability", + "text": "Consider an appropriate node size, not too large or too small", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "bf39d95d-44c7-4c89-89ca-1f6d5315ae52", + "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": [ + "AKS" + ], "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" + "subcategory": "Scalability", + "text": "If more than 5000 nodes are required for scalability then consider using an additional AKS cluster", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "4ba34d45-85e1-4213-abd7-bb012f7b95ef", - "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" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Scalability", + "text": "Consider subscribing to EventGrid Events for AKS automation", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "6e043e2a-a359-4271-ae6e-205172676ae4", + "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": [ + "AKS" + ], "severity": "Low", - "subcategory": "Governance (platform)", - "text": "Are Azure reserved instances used to optimize cost for using Azure VMware Solution" + "subcategory": "Scalability", + "text": "For long running operation on an AKS cluster consider event termination", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "6691e883-5ac9-4422-83e1-3810523081a9", - "severity": "Medium", - "subcategory": "Governance (platform)", - "text": "Consider the use of Azure Private-Link when using other Azure Native Services" + "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": [ + "AKS" + ], + "severity": "Low", + "subcategory": "Scalability", + "text": "If required consider using Azure Dedicated Hosts for AKS nodes", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "48b262d6-cc5f-4512-a253-98e6db9d37da", - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Enable Microsoft Defender for Cloud for Azure VMware Solution guest VM workloads" + "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": [ + "Storage", + "AKS" + ], + "severity": "High", + "subcategory": "Storage", + "text": "Use ephemeral OS disks", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "41741583-3ef7-4ad7-a6d3-733165c7acbe", - "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Use Azure ARC enabled servers to manage your Azure VMware Solution guest VM workloads" + "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": [ + "Storage", + "AKS" + ], + "severity": "High", + "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": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "88f03a4d-2cd4-463c-abbc-868295abc91a", - "severity": "High", - "subcategory": "Governance (guest/VM)", - "text": "Enable Diagnostic and metric logging on Azure VMware Solution" + "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": [ + "Storage", + "AKS" + ], + "severity": "Low", + "subcategory": "Storage", + "text": "For hyper performance storage option use Ultra Disks on AKS", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "4ed90dae-2cc8-44c4-9b6b-781cbafe6c46", + "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": [ + "SQL", + "AKS", + "Storage" + ], "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Deploy the Log Analytics Agents to Azure VMware Solution guest VM workloads" + "simple": -1, + "subcategory": "Storage", + "text": "Avoid keeping state in the cluster, and store data outside (AzStorage, AzSQL, Cosmos, etc)", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "589d457a-927c-4397-9d11-02cad6aae11e", + "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": [ + "Storage", + "AKS" + ], "severity": "Medium", - "subcategory": "Governance (guest/VM)", - "text": "Ensure you have a documented and implemented backup policy and solution for Azure VMware Solution VM workloads" + "subcategory": "Storage", + "text": "If using AzFiles Standard, consider AzFiles Premium and/or ANF for performance reasons", + "waf": "Performance" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "ee29711b-d352-4caa-ab79-b198dab81932", + "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": [ + "Storage", + "AKS" + ], "severity": "Medium", - "subcategory": "Compliance", - "text": "Use MDfC for compliance monitoring of workloads running on Azure VMware Solution" + "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": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "c9fc9d1b-b780-436f-9e6b-fbb9ed503547", - "severity": "Medium", - "subcategory": "Compliance", - "text": "Are the applicable compliance baselines added to MDfC" + "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", + "link": "https://learn.microsoft.com/azure/container-registry/data-loss-prevention", + "services": [ + "ACR" + ], + "severity": "High", + "subcategory": "Data Protection", + "text": "Disable Azure Container Registry image export" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "cc447e82-6128-4a71-b0f1-cac6d9ef1d5e", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-azure-policy", + "services": [ + "ACR", + "AzurePolicy" + ], "severity": "High", - "subcategory": "Compliance", - "text": "Was data residency evaluated when selecting Azure regions to use for Azure VMware Solution deployment" + "subcategory": "Data Protection", + "text": "Enable Azure Policies for Azure Container Registry" }, { - "category": "Governance", - "checklist": "Azure VMware Solution Review", - "guid": "832e42e3-611c-4818-a0a0-bc510e43a18a", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-tutorial-sign-build-push", + "services": [ + "ACR", + "AKV" + ], "severity": "High", - "subcategory": "Compliance", - "text": "Are data processing implications (service provider / service consumer model) clear and documented" + "subcategory": "Data Protection", + "text": "Sign and Verify containers with notation (Notary v2)" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "e43a18a9-cd28-49ce-b6b1-7db8255461e2", - "severity": "High", - "subcategory": "Monitoring", - "text": "Create dashboards to enable core Azure VMware Solution monitoring insights" + "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", + "link": "https://learn.microsoft.com/azure/container-registry/tutorial-customer-managed-keys", + "services": [ + "ACR", + "AKV" + ], + "severity": "Medium", + "subcategory": "Data Protection", + "text": "Encrypt registry with a customer managed key" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "6b84ee5d-f47d-42d9-8881-b1cd5d1e54a2", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", + "services": [ + "ACR", + "RBAC", + "Entra" + ], "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%)" + "subcategory": "Identity and Access Control", + "text": "Use Managed Identities to connect instead of Service Principals" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "9659e396-80e7-4828-ac93-5657d02bff45", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication-managed-identity", + "services": [ + "ACR", + "RBAC", + "Entra" + ], "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" + "subcategory": "Identity and Access Control", + "text": "Disable local authentication for management plane access" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "64b0d934-a348-4726-be79-d6b5c3a36495", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-roles?tabs=azure-cli", + "services": [ + "ACR", + "RBAC", + "Entra" + ], "severity": "High", - "subcategory": "Monitoring", - "text": "Ensure alerts are configured for Azure Service Health alerts and notifications" + "subcategory": "Identity and Access Control", + "text": "Assign AcrPull & AcrPush RBAC roles rather than granting Administrative access to identity principals" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "b6abad38-aad5-43cc-99e1-d86667357c54", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Disable anonymous pull/push access", + "guid": "e338997e-41c7-47d7-acf6-a62a1194956d", + "link": "https://learn.microsoft.com/azure/container-registry/anonymous-pull-access#configure-anonymous-pull-access", + "services": [ + "ACR", + "Entra" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Configure Azure VMware Solution logging to be send to an Azure Storage account or Azure EventHub for processing" + "subcategory": "Identity and Access Control", + "text": "Disable Anonymous pull access" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "9674c5ed-85b8-459c-9733-be2b1a27b775", - "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?" + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-authentication?tabs=azure-cli", + "services": [ + "ACR", + "Entra" + ], + "severity": "High", + "subcategory": "Identity and Access Control", + "text": "Disable repository-scoped access tokens" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "a91be1f3-88f0-43a4-b2cd-463cbbbc8682", + "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", + "services": [ + "ACR", + "EventHubs", + "PrivateLink", + "Entra" + ], "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" + "subcategory": "Identity and Access Control", + "text": "Deploy images from a trusted environment" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "d9ef1d5e-832d-442e-9611-c818b0afbc51", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-enable-conditional-access-policy", + "services": [ + "ACR", + "AzurePolicy", + "Entra" + ], "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure vSphere content libraries are not placed on vSAN as vSAN is a finite resource" + "subcategory": "Identity and Access Control", + "text": "Disable Azure ARM audience tokens for authentication" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "0e43a18a-9cd2-489b-bd6b-17db8255461e", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/monitor-service", + "services": [ + "ACR", + "Monitor", + "Entra" + ], "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" + "subcategory": "Logging and Monitoring", + "text": "Enable diagnostics logging" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "2aee3453-aec8-4339-848b-262d6cc5f512", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-private-link", + "services": [ + "ACR", + "VNet", + "PrivateLink", + "Firewall" + ], "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 not yet available)" + "subcategory": "Network Security", + "text": "Control inbound network access with Private Link" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "925398e6-da9d-437d-ac43-bc6cd1d79a9b", + "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", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-access-selected-networks#disable-public-network-access", + "services": [ + "ACR", + "PrivateLink" + ], "severity": "Medium", - "subcategory": "Operations", - "text": "Ensure workloads running on Azure VMware Solution are monitored using Azure Log Analytics and Azure Monitor" + "subcategory": "Network Security", + "text": "Disable Public Network access" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "24604489-a8f4-42d7-ae78-cb6a33bd2a09", + "category": "Security", + "checklist": "Azure Container Registry Security Review", + "description": "Only the ACR Premium SKU supports Private Link access", + "guid": "fc833934-8b26-42d6-ac5f-512925498f6d", + "link": "https://learn.microsoft.com/azure/container-registry/container-registry-skus", + "services": [ + "ACR", + "PrivateLink" + ], "severity": "Medium", - "subcategory": "Operations", - "text": "Include workloads running on Azure VMware Solution in existing update management tooling or in Azure Update Management" + "subcategory": "Network Security", + "text": "Use an Azure Container Registry SKU that supports Private Link (Premium SKU)" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "17e7a8d9-0ae0-4e27-aee2-9711bd352caa", + "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", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/defender-for-containers-introduction", + "services": [ + "ACR", + "Defender" + ], + "severity": "Low", + "subcategory": "Network Security", + "text": "Enable Defender for Containers to scan Azure Container Registry for vulnerabilities" + }, + { + "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", + "services": [ + "ACR" + ], "severity": "Medium", - "subcategory": "Operations", - "text": "Use Azure Policy to onboard Azure VMware Solution workloads in the Azure Management, Monitoring and Security solutions" + "subcategory": "Vulnerability Management", + "text": "Deploy validated container images" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "ab79b188-dab8-4193-8c9f-c9d1bb77036f", + "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", + "services": [ + "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)" + "subcategory": "Vulnerability Management", + "text": "Use up-to-date platforms, languages, protocols and frameworks" }, { - "category": "Management", - "checklist": "Azure VMware Solution Review", - "guid": "aee3553a-fc83-4392-98b2-62d6cc5f5129", - "severity": "Medium", - "subcategory": "Security", - "text": "Ensure workloads running on Azure VMware Solution are onboarded to Microsoft Defender for Cloud" + "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": [ + "ServiceBus" + ], + "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": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "25398e6d-b9d3-47da-a43b-c6cd1d79a9b2", + "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": [ + "ServiceBus" + ], "severity": "Medium", - "subcategory": "Backup", - "text": "Ensure backups are not stored on vSAN as vSAN is a finite resource" + "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": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "5e6bfbb9-ed50-4354-9cc4-47e826028a71", + "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", + "ServiceBus", + "Entra", + "RBAC", + "TrafficManager" + ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use VMware Site Recovery Manager when both sites are Azure VMware Solution" + "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": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "f0f1cac6-d9ef-41d5-b832-d42e3611c818", + "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": [ + "VM", + "AKV", + "ServiceBus", + "AppSvc", + "Entra", + "Storage" + ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use Azure Site Recovery when the Disaster Recovery technology is native Azure IaaS" + "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": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "b0afbc51-0e43-4a18-a9cd-289bed6b17db", + "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": [ + "Subscriptions", + "ServiceBus", + "Entra", + "RBAC", + "Storage" + ], "severity": "High", - "subcategory": "Disaster Recovery", - "text": "Use Automated recovery plans with either of the Disaster solutions, avoid manual tasks as much as possible" + "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": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "8255461e-2aee-4345-9aec-8339248b262d", + "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": [ + "VNet", + "ServiceBus", + "Monitor" + ], "severity": "Medium", - "subcategory": "Disaster Recovery", - "text": "Use the geopolitical region pair as the secondary disaster recovery environment" - }, - { - "category": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "6cc5f512-9253-498e-9da9-d37dac43bc6c", - "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" + "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": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "d1d79a9b-2460-4448-aa8f-42d78e78cb6a", - "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?" - }, - { - "category": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "33bd2a09-17e7-4a8d-a0ae-0e27cee29711", - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Use MABS as your backup solution" - }, - { - "category": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "bd352caa-ab79-4b18-adab-81932c9fc9d1", - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Deploy your backup solution in the same region as your Azure VMware Solution private cloud" - }, - { - "category": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "bb77036f-5e6b-4fbb-aed5-03547cc447e8", - "severity": "Medium", - "subcategory": "Business Continuity", - "text": "Preferably deploy MABS outside of the SDDC as native Azure IaaS" - }, - { - "category": "BCDR", - "checklist": "Azure VMware Solution Review", - "guid": "26028a71-f0f1-4cac-9d9e-f1d5e832d42e", - "severity": "Low", - "subcategory": "Business Continuity", - "text": "Is a process in place to request a restore of the VMware components managed by the Azure Platform?" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "4604489a-8f42-4d78-b78c-b7a33bd2a0a1", - "severity": "Low", - "subcategory": "Deployment strategy", - "text": "For manual deployments, all configuration and deployments must be documented" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "7e7a8d90-ae0e-437c-be29-711bd352caaa", - "severity": "Low", - "subcategory": "Deployment strategy", - "text": "For manual deployments, consider implementing resource locks to prevent accidental actions on your Azure VMware Solution Private Cloud" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "b79b198d-ab81-4932-a9fc-9d1bb78036f5", - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployments, deploy a minimal private cloud and scale as needed" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "e6bfbb9e-d503-4547-ac44-7e826128a71f", - "severity": "Low", - "subcategory": "Automated Deployment", - "text": "For automated deployments, request or reserve quota prior to starting the deployment" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "0f1cac6d-9ef1-4d5e-a32e-42e3611c818b", - "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" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "e2cc95d4-8c6b-4791-bca0-f6c56589e558", - "severity": "Low", - "subcategory": "Automated Connectivity", - "text": "Implement human understandable names for ExR authorization keys to allow for easy identification of the keys purpose/use" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "255461e2-aee3-4553-afc8-339248b262d6", - "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" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "cc5f5129-2539-48e6-bb9d-37dac43bc6cd", - "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." - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "1d79a9b2-4604-4489-a8f4-2d78e78cb7a3", - "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" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "3bd2a0a1-7e7a-48d9-8ae0-e37cee29711b", - "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" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "d352caaa-b79b-4198-bab8-1932c9fc9d1b", - "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" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "b78036f5-e6bf-4bb9-bd50-3547cc447e82", - "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)" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "bf15bce2-19e4-4a0e-a588-79424d226786", - "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Consider and validate scaling operations on 3rd party solutions used in the architecture (supported or not)" - }, - { - "category": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "d20b56c5-7be5-4851-a0f8-3835c586cb29", + "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": [ + "VNet", + "ServiceBus", + "PrivateLink" + ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Define and enforce scale in/out maximum limits for your environment in the automations" + "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": "Platform Automation", - "checklist": "Azure VMware Solution Review", - "guid": "1dc15a1c-075e-4e9f-841a-cccd579376bc", + "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": [ + "ServiceBus" + ], "severity": "Medium", - "subcategory": "Automated Scale", - "text": "Implement monitoring rules to monitor automated scaling operations and monitor success and failure to enable appropriate (automated) responses" + "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": "Security", @@ -3933,6 +6782,9 @@ "description": "Apply guidance from the Microsoft cloud security benchmark related to Storage", "guid": "d237de14-3b16-4c21-b7aa-9b64604489a8", "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/storage-security-baseline", + "services": [ + "Storage" + ], "severity": "Medium", "subcategory": " Overview", "text": "Consider the 'Azure security baseline for storage'" @@ -3943,6 +6795,10 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/storage-private-endpoints", + "services": [ + "Storage", + "PrivateLink" + ], "severity": "High", "subcategory": "Networking", "text": "Consider using private endpoints for Azure Storage" @@ -3953,6 +6809,11 @@ "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", "link": "https://learn.microsoft.com/azure/virtual-machines/migration-classic-resource-manager-overview#migration-of-storage-accounts", + "services": [ + "Subscriptions", + "Storage", + "RBAC" + ], "severity": "Medium", "subcategory": "Governance", "text": "Ensure older storage accounts are not using 'classic deployment model'" @@ -3963,6 +6824,10 @@ "description": "Leverage Microsoft Defender to learn about suspicious activity and misconfigurations.", "guid": "fc5972cd-4cd2-41b0-a803-7f5e6b4bfd3d", "link": "https://learn.microsoft.com/azure/storage/common/azure-defender-storage-configure", + "services": [ + "Storage", + "Defender" + ], "severity": "High", "subcategory": "Governance", "text": "Enable Microsoft Defender for all of your storage accounts" @@ -3973,6 +6838,9 @@ "description": "The soft-delete mechanism allows to recover accidentally deleted blobs.", "guid": "503547c1-447e-4c66-828a-7100f1ce16dd", "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-overview", + "services": [ + "Storage" + ], "severity": "Medium", "subcategory": "Data Availability", "text": "Enable 'soft delete' for blobs" @@ -3983,6 +6851,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-enable", + "services": [ + "Storage" + ], "severity": "Medium", "subcategory": "Confidentiality", "text": "Disable 'soft delete' for blobs" @@ -3993,6 +6864,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-overview", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Data Availability", "text": "Enable 'soft delete' for containers" @@ -4003,6 +6877,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/soft-delete-container-enable", + "services": [ + "Storage" + ], "severity": "Medium", "subcategory": "Confidentiality", "text": "Disable 'soft delete' for containers" @@ -4013,6 +6890,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/lock-account-resource", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Data Availability", "text": "Enable resource locks on storage accounts" @@ -4023,6 +6903,11 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/immutable-storage-overview", + "services": [ + "AzurePolicy", + "Subscriptions", + "Storage" + ], "severity": "High", "subcategory": "Data Availability, Compliance", "text": "Consider immutable blobs" @@ -4033,6 +6918,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Networking", "text": "Require HTTPS, i.e. disable port 80 on the storage account" @@ -4043,6 +6931,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/storage-custom-domain-name", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Networking", "text": "When enforcing HTTPS (disabling HTTP), check that you do not use custom domains (CNAME) for the storage account." @@ -4053,6 +6944,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview", + "services": [ + "Storage" + ], "severity": "Medium", "subcategory": "Networking", "text": "Limit shared access signature (SAS) tokens to HTTPS connections only" @@ -4063,6 +6957,10 @@ "description": "AAD tokens should be favored over shared access signatures, wherever possible", "guid": "e1ce15dd-3f0d-45e7-92d4-1e3611cc57b4", "link": "https://learn.microsoft.com/azure/storage/common/authorize-data-access", + "services": [ + "Storage", + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Management", "text": "Use Azure Active Directory (Azure AD) tokens for blob access" @@ -4072,6 +6970,11 @@ "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", + "services": [ + "Storage", + "RBAC", + "Entra" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "Least privilege in IaM permissions" @@ -4082,6 +6985,10 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/storage-sas-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json#best-practices-when-using-sas", + "services": [ + "Storage", + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Management", "text": "When using SAS, prefer 'user delegation SAS' over storage-account-key based SAS." @@ -4092,6 +6999,12 @@ "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", "link": "https://learn.microsoft.com/rest/api/storageservices/authorize-with-shared-key", + "services": [ + "Storage", + "Monitor", + "Entra", + "AKV" + ], "severity": "High", "subcategory": "Identity and Access Management", "text": "Consider disabling storage account keys, so that only AAD access (and user delegation SAS) is supported." @@ -4102,6 +7015,12 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/blob-storage-monitoring-scenarios#audit-account-activity", + "services": [ + "AzurePolicy", + "Storage", + "Monitor", + "AKV" + ], "severity": "High", "subcategory": "Monitoring", "text": "Consider using Azure Monitor to audit control plane operations on the storage account" @@ -4112,6 +7031,12 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/storage-account-keys-manage?tabs=azure-portal#create-a-key-expiration-policy", + "services": [ + "AzurePolicy", + "Storage", + "Entra", + "AKV" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "When using storage account keys, consider enabling a 'key expiration policy'" @@ -4122,6 +7047,11 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/sas-expiration-policy", + "services": [ + "AzurePolicy", + "Storage", + "Entra" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "Consider configuring an SAS expiration policy" @@ -4132,6 +7062,12 @@ "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", "link": "https://learn.microsoft.com/rest/api/storageservices/define-stored-access-policy", + "services": [ + "AzurePolicy", + "Storage", + "Entra", + "AKV" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "Consider linking SAS to a stored access policy" @@ -4141,6 +7077,10 @@ "checklist": "Azure Blob Storage Review", "guid": "028a71ff-e1ce-415d-b3f0-d5e772d41e36", "link": "https://microsoft.github.io/code-with-engineering-playbook/continuous-integration/dev-sec-ops/secret-management/recipes/detect-secrets-ado/", + "services": [ + "Storage", + "AKV" + ], "severity": "Medium", "subcategory": "CI/CD", "text": "Consider configuring your application's source code repository to detect checked-in connection strings and storage account keys." @@ -4151,6 +7091,10 @@ "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", "link": "https://learn.microsoft.com/azure/architecture/framework/security/design-storage-keys", + "services": [ + "Storage", + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Management", "text": "Consider storing connection strings in Azure KeyVault (in scenarios where managed identities are not possible)" @@ -4161,6 +7105,11 @@ "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", "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", + "services": [ + "AzurePolicy", + "Storage", + "Entra" + ], "severity": "High", "subcategory": "Identity and Access Management", "text": "Strive for short validity periods for ad-hoc SAS" @@ -4171,6 +7120,10 @@ "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", "link": "https://learn.microsoft.com/rest/api/storageservices/delegate-access-with-shared-access-signature", + "services": [ + "Storage", + "Entra" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "Apply a narrow scope to a SAS" @@ -4181,6 +7134,10 @@ "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", "link": "https://learn.microsoft.com/rest/api/storageservices/create-account-sas", + "services": [ + "Storage", + "Entra" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "Consider scoping SAS to a specific client IP address, wherever possible" @@ -4190,6 +7147,10 @@ "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", + "services": [ + "Storage", + "Entra" + ], "severity": "Low", "subcategory": "Identity and Access Management", "text": "Consider checking uploaded data, after clients used a SAS to upload a file. " @@ -4200,6 +7161,11 @@ "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", "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-support#sftp-permission-model", + "services": [ + "Storage", + "RBAC", + "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." @@ -4209,6 +7175,10 @@ "checklist": "Azure Blob Storage Review", "guid": "9f89dc7b-33be-42a1-a27f-7b9e91be1f38", "link": "https://learn.microsoft.com/azure/storage/blobs/secure-file-transfer-protocol-known-issues#authentication-and-authorization", + "services": [ + "Storage", + "Entra" + ], "severity": "Medium", "subcategory": "Identity and Access Management", "text": "SFTP: The SFTP endpoint does not support POSIX-like ACLs." @@ -4219,6 +7189,10 @@ "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", "link": "https://learn.microsoft.com/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services", + "services": [ + "AzurePolicy", + "Storage" + ], "severity": "High", "subcategory": "Networking", "text": "Avoid overly broad CORS policies" @@ -4229,6 +7203,9 @@ "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", "link": "https://learn.microsoft.com/azure/storage/common/storage-service-encryption", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Confidentiality and Encryption", "text": "Determine how data at rest should be encrypted. Understand the thread model for data." @@ -4238,6 +7215,9 @@ "checklist": "Azure Blob Storage Review", "guid": "8dd457e9-2713-48b8-8110-2cac6eae01e6", "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": [ + "Storage" + ], "severity": "Medium", "subcategory": "Confidentiality and Encryption", "text": "Determine which/if platform encryption should be used." @@ -4247,6 +7227,9 @@ "checklist": "Azure Blob Storage Review", "guid": "e842e52f-4721-4d92-ac1b-1cd521e54a29", "link": "https://learn.microsoft.com/azure/storage/blobs/encryption-customer-provided-keys", + "services": [ + "Storage" + ], "severity": "Medium", "subcategory": "Confidentiality and Encryption", "text": "Determine which/if client-side encryption should be used." @@ -4257,3145 +7240,4211 @@ "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", "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": [ + "Storage", + "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. " }, - { - "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", - "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", - "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/" - }, - { - "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", - "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": "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", - "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/" - }, - { - "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", - "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", - "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", - "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/" - }, - { - "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", - "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": "Backup and Disaster Recovery", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", - "link": "https://learn.microsoft.com/en-us/azure/reliability/cross-region-replication-azure", + "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", + "services": [ + "ASR", + "Backup" + ], "severity": "Medium", "subcategory": "Data Protection", - "text": "Consider cross-region replication in Azure for BCDR with paired regions" + "text": "Consider cross-region replication in Azure for BCDR with paired regions", + "waf": "Reliability" }, { "category": "Backup and Disaster Recovery", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", - "link": "https://learn.microsoft.com/en-us/azure/storage/common/storage-redundancy", + "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", + "services": [ + "ASR", + "Backup" + ], "severity": "Medium", "subcategory": "Data Protection", - "text": "When using Azure Backup, consider the different backup types (GRS, ZRS & LRS) as the default setting is GRS" + "text": "When using Azure Backup, consider the different backup types (GRS, ZRS & LRS) as the default setting is GRS", + "waf": "Reliability" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "984a859c-773e-47d2-9162-3a765a917e1f", "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", + "services": [ + "Entra" + ], "severity": "High", "subcategory": "Identity", "text": "Implement for emergency access or break-glass accounts to prevent tenant-wide account lockout", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "348ef254-c27d-442e-abba-c7571559ab91", "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "services": [ + "Subscriptions", + "RBAC", + "Entra" + ], "severity": "High", "subcategory": "Identity", "text": "Enforce a RBAC model for management groups, subscriptions, resource groups and resources", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", + "services": [ + "AzurePolicy", + "Entra" + ], "severity": "Low", "subcategory": "Identity", "text": "Enforce Azure AD conditional-access policies for any user with rights to Azure environments", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/" + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", + "services": [ + "Entra" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", - "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", + "services": [ + "RBAC", + "Entra" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "14658d35-58fd-4772-99b8-21112df27ee4", "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "services": [ + "Entra" + ], "severity": "Medium", "subcategory": "Identity", "text": "Enforce Azure AD Privileged Identity Management (PIM) to establish zero standing access and least privilege", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", "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": [ + "Entra" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", "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/" + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "f5664b5e-984a-4859-a773-e7d261623a76", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", + "services": [ + "Subscriptions", + "RBAC", + "Entra" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", + "services": [ + "AzurePolicy", + "Entra" + ], "severity": "Medium", "subcategory": "Identity", "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "services": [ + "Subscriptions", + "Entra" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", + "services": [ + "Entra" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "services": [ + "Entra" + ], "severity": "Medium", "subcategory": "Identity", "text": "If AD on Windows server in use, can all required resources access correct domain controller?", - "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/" + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", + "services": [ + "VPN", + "Entra" + ], "severity": "Medium", "subcategory": "Identity", "text": "Consider using Azure AD 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/" + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Security" }, { "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "35037e68-9349-4c15-b371-228514f4cdff", "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", + "services": [ + "RBAC", + "Entra" + ], "severity": "Medium", "subcategory": "Identity", "text": "Avoid using on-premises synced accounts for Azure AD role assignments.", - "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/" + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", + "services": [ + "Subscriptions" + ], "severity": "Medium", "subcategory": "Subscriptions", "text": "Enforce reasonably flat management group hierarchy with no more than three to four levels, ideally", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", + "services": [ + "AzurePolicy", + "Subscriptions" + ], "severity": "Medium", "subcategory": "Subscriptions", "text": "Enforce or appended resource tags through Azure Policy", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "667313b4-f566-44b5-b984-a859c773e7d2", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", + "services": [ + "Subscriptions" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", + "services": [ + "AzurePolicy", + "Subscriptions", + "RBAC" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", + "services": [ + "Subscriptions", + "ExpressRoute", + "DNS", + "VWAN" + ], "severity": "Medium", "subcategory": "Subscriptions", "text": "Enforce a dedicated connectivity subscription in the Platform 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/" + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", + "services": [ + "Subscriptions" + ], "severity": "Medium", "subcategory": "Subscriptions", - "text": "Enforce no subscriptions are placed under the root management group" + "text": "Enforce no subscriptions are placed under the root management group", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", + "services": [ + "Subscriptions", + "RBAC" + ], "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" + "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": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "services": [ + "Subscriptions" + ], "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." + "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": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "49b82111-2df2-47ee-912e-7f983f630472", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "services": [ + "AzurePolicy", + "Cost", + "RBAC", + "Subscriptions" + ], "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." + "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": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", "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 resource limitations as part of workload design sessions." + "text": "Ensure that all subscription owners and IT core team are aware of subscription resource limitations as part of workload design sessions.", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", + "services": [ + "AzurePolicy", + "Cost", + "Subscriptions", + "VM" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/improve-reliability-modern-operations/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", + "services": [ + "Subscriptions", + "Monitor" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/monitor-usage-performance-availability-resources-azure-monitor/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", "link": "https://azure.microsoft.com/global-infrastructure/services/", + "services": [ + "Subscriptions" + ], "severity": "Medium", "subcategory": "Subscriptions", "text": "Ensure required services and features are available within the chosen deployment regions", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", + "services": [ + "Cost", + "Subscriptions" + ], "severity": "High", "subcategory": "Subscriptions", "text": "Enforce a process for cost management", - "training": "https://learn.microsoft.com/learn/paths/control-spending-manage-bills/" + "training": "https://learn.microsoft.com/learn/paths/control-spending-manage-bills/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "services": [ + "Subscriptions", + "Entra" + ], "severity": "Medium", "subcategory": "Subscriptions", "text": "If AD on Windows Server, establish a dedicated identity subscription in the Platform management group to host Windows Server Active Directory domain controllers", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "waf": "Security" }, { "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", + "services": [ + "Cost", + "Subscriptions" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", + "services": [ + "FrontDoor", + "Monitor", + "WAF" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Add diagnostic settings to save your Azure Front Door WAF's logs. Regularly review the logs to check for attacks and for false positive detections." + "subcategory": "App delivery", + "text": "Add diagnostic settings to save your Azure Front Door WAF's logs. Regularly review the logs to check for attacks and for false positive detections.", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "7f408960-c626-44cb-a018-347c8d790cdf", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", + "services": [ + "FrontDoor", + "Monitor", + "Sentinel" + ], "severity": "Medium", - "subcategory": "Front Door", - "text": "Send Azure Front Door logs to Microsoft Sentinel. Detect attacks and integrate Front Door telemetry into your overall Azure environment." + "subcategory": "App delivery", + "text": "Send Azure Front Door logs to Microsoft Sentinel. Detect attacks and integrate Front Door telemetry into your overall Azure environment.", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "AzurePolicy", + "Monitor", + "RBAC", + "Entra" + ], "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" + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "services": [ + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Is the landing zone documented?" + "text": "Is the landing zone documented?", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "AzurePolicy", + "Storage", + "ARS", + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", "text": "Export logs to Azure Storage if log retention requirements exceed two years. Use immutable storage with a write-once, read-many policy to make data non-erasable and non-modifiable for a user-specified interval.", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "AzurePolicy", + "Monitor" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", + "services": [ + "AzurePolicy", + "Monitor", + "VM" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", "link": "https://learn.microsoft.com/azure/automation/update-management/overview", + "services": [ + "Monitor", + "VM" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "90483845-c986-4cb2-a131-56a12476e49f", "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", + "services": [ + "Monitor", + "NetworkWatcher" + ], "severity": "Medium", "subcategory": "Monitoring", "text": "Use Network Watcher to proactively monitor traffic flows", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", + "services": [ + "Monitor" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy", + "Monitor", + "RBAC" + ], "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." + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", + "services": [ + "Monitor" + ], "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." + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", + "services": [ + "Monitor" + ], "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" + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "services": [ + "Monitor" + ], "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." + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "9945bda4-3334-4f24-a116-34182ba52752", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "Monitor", + "RBAC", + "Entra" + ], "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." + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", + "services": [ + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Use Azure Monitor Logs for insights and reporting." + "text": "Use Azure Monitor Logs for insights and reporting.", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", + "services": [ + "Storage", + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage." + "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage.", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "97be9951-9048-4384-9c98-6cb2913156a1", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", + "services": [ + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Use Azure Monitor alerts for the generation of operational alerts." + "text": "Use Azure Monitor alerts for the generation of operational alerts.", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", + "services": [ + "ACR", + "ASR", + "Monitor", + "VM" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Use Azure Site Recovery for Azure-to-Azure Virtual Machines disaster recovery scenarios. This enables you to replicate workloads across regions." + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", + "services": [ + "ASR", + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Ensure to use and test native PaaS service disaster recovery capabilities." + "text": "Ensure to use and test native PaaS service disaster recovery capabilities.", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", + "services": [ + "Monitor", + "Backup" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Use Azure-native backup capabilities. Verify that partner/customer is aware of Azure Backup and all new capabilities which greatly can simplify backup management" + "text": "Use Azure-native backup capabilities. Verify that partner/customer is aware of Azure Backup and all new capabilities which greatly can simplify backup management", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "859c3900-4514-41eb-b010-475d695abd74", "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", + "services": [ + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied" + "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied", + "waf": "Operations" }, { "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", - "link": "https://learn.microsoft.com/en-us/azure/automation/how-to/region-mappings", + "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", + "services": [ + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Consider supported regions for linked Log Analytics workspace and automation accounts" + "text": "Consider supported regions for linked Log Analytics workspace and automation accounts", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", - "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", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "services": [ + "FrontDoor", + "AKV" + ], "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/" + "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" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = (properties.webApplicationFirewallConfiguration.enabled == True and properties.webApplicationFirewallConfiguration.firewallMode == 'Prevention')", - "guid": "611cc58b-5a4b-4151-8e43-a58a9c2299c4", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/application-gateway-waf-faq", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "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": "For secure delivery of HTTP/S apps, ensure that WAF protection and policies are enabled in your Application Gateways", - "training": "https://learn.microsoft.com/learn/paths/secure-application-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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "services": [ + "AppGW" + ], "severity": "Medium", "subcategory": "App delivery", "text": "Ensure you are using Application Gateway v2 SKU", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d7b57d0c-6555-462f-8b3e-4563a4d87397", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/organize-resources?tabs=AzureManagementGroupsAndHierarchy", + "checklist": "Azure Landing Zone Review (old version)", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "services": [ + "LoadBalancer" + ], "severity": "Medium", "subcategory": "App delivery", - "text": "Use a partner NVA if you can't use Application Gateway v2 for the security of HTTP/S apps.", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", + "services": [ + "AppGW", + "VNet" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "description": "Administration of reverse proxies in general and WAF in particular is closer to the application than to networking, so they belong in the same subscription as the app. Centralizing the Application Gateway and WAF in the connectivity subscription might be OK if it is managed by one single team.", "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "Subscriptions", + "Entra", + "WAF", + "AppGW", + "NVA", + "VNet" + ], "severity": "Medium", "subcategory": "App delivery", - "text": "Deploy Azure Application Gateway v2 or partner NVAs used for 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/" + "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" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "DDoS" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "AzurePolicy", + "FrontDoor", + "WAF" + ], "severity": "Medium", "subcategory": "App delivery", - "text": "Use Azure Front Door with WAF policies to deliver and help protect global HTTP/S apps that span Azure regions.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" + "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 Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "services": [ + "AppGW", + "FrontDoor", + "AzurePolicy", + "WAF" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "severity": "Medium", + "services": [ + "TrafficManager" + ], + "severity": "High", "subcategory": "App delivery", "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "services": [ + "Entra", + "AVD" + ], "severity": "Low", "subcategory": "App delivery", "text": "If users only need access to internal applications, has Azure AD Application Proxy been considered as an alternative to Azure Virtual Desktop (AVD)?", - "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/" + "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "services": [ + "Entra" + ], "severity": "Medium", "subcategory": "App delivery", "text": "To reduce the number of firewall ports open for incoming connections in your network, consider using Azure AD Application Proxy to give remote users secure and authenticated access to internal applications.", - "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", - "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." - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", - "severity": "Medium", - "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", - "severity": "Medium", - "subcategory": "Front Door", - "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode." + "services": [ + "FrontDoor", + "Storage", + "WAF" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", + "services": [ + "FrontDoor", + "TrafficManager" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Avoid combining Azure Traffic Manager and Azure Front Door." + "subcategory": "App delivery", + "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", - "severity": "Medium", - "subcategory": "Front Door", - "text": "Use the same domain name on Azure Front Door and your origin. Mismatched host names can cause subtle bugs." + "services": [ + "FrontDoor" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Use the same domain name on Azure Front Door and your origin. Mismatched host names can cause subtle bugs.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", "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": "Front Door", - "text": "Disable health probes when there is only one origin in an Azure Front Door origin group." + "subcategory": "App delivery", + "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", + "services": [ + "FrontDoor" + ], "severity": "Medium", - "subcategory": "Front Door", - "text": "Select good health probe endpoints for Azure Front Door. Consider building health endpoints that check all of your application's dependencies." + "subcategory": "App delivery", + "text": "Select good health probe endpoints for Azure Front Door. Consider building health endpoints that check all of your application's dependencies.", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", + "services": [ + "FrontDoor" + ], "severity": "Low", - "subcategory": "Front Door", - "text": "Use HEAD health probes with Azure Front Door, to reduce the traffic that Front Door sends to your application." + "subcategory": "App delivery", + "text": "Use HEAD health probes with Azure Front Door, to reduce the traffic that Front Door sends to your application.", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", + "services": [ + "LoadBalancer" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", + "waf": "Reliability" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "services": [ + "ExpressRoute" + ], + "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", + "services": [ + "VPN", + "ExpressRoute" + ], + "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", + "services": [ + "VNet" + ], "severity": "Medium", "subcategory": "Hub and spoke", - "text": "Consider a network design based on the traditional hub-and-spoke network topology for the following scenarios: a network architecture deployed within a single Azure region; a network architecture spans multiple Azure regions with no need for transitive connectivity between virtual networks for landing zones across regions; a network architecture that spans multiple Azure regions with global VNet peering used to connect virtual networks across Azure regions; a network architecture with no need for transitive connectivity between VPN and ExpressRoute connections; the main hybrid connectivity method in place is ExpressRoute, and the number of VPN connections is less than 30 per VPN gateway; there's a dependency on centralized NVAs and granular routing.", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", - "severity": "Medium", + "services": [ + "VPN", + "Entra", + "NVA", + "VNet", + "ExpressRoute", + "Firewall", + "DNS" + ], + "severity": "High", "subcategory": "Hub and spoke", - "text": "Ensure that shared services, including ExpressRoute gateways, VPN gateways, and Azure Firewall or partner NVAs in the central-hub virtual network. If necessary, also deploy Active Directory domain controllers and DNS servers." + "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 Active Directory domain controllers and DNS servers.", + "waf": "Cost" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", + "services": [ + "NVA" + ], "severity": "Medium", "subcategory": "Hub and spoke", - "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance" + "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "44ce3b1a-2808-4b9e-a1bf-1038df03a822", - "link": "https://azure.microsoft.com/solutions/network-appliances/", - "severity": "Medium", - "subcategory": "Hub and spoke", - "text": "Do not deploy inbound L7 services such as Azure Application Gateway as a shared service in the central-hub virtual network. Instead, deploy them together with the app in their respective landing zones." - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", - "severity": "Medium", + "services": [ + "VPN", + "ARS", + "ExpressRoute" + ], + "severity": "Low", "subcategory": "Hub and spoke", - "text": "If you need transit between ExpressRoute and VPN gateways, use Azure Route Server." + "text": "If you need transit between ExpressRoute and VPN gateways in hub and spoke scenarios, use Azure Route Server.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-faq#can-i-create-a-peering-connection-to-a-vnet-in-a-different-region", - "severity": "Medium", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", + "services": [ + "VNet", + "ARS" + ], + "severity": "Low", "subcategory": "Hub and spoke", - "text": "For network architectures with multiple hub-and-spoke topologies across Azure regions, use Global Virtual Network Peering to connect landing-zone virtual networks when a small number of landing zones need to communicate across regions. ", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-virtual-networks/" + "text": "If using Route Server, use a /27 prefix for the Route Server subnet.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "37239b82-1112-4dbd-9eaf-12e6f943e53f", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "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": [ + "ACR", + "VNet" + ], "severity": "Medium", "subcategory": "Hub and spoke", - "text": "When you deploy a hub-and-spoke network architecture in two Azure regions and transit connectivity between all landing zones across regions is required, use ExpressRoute with dual circuits to provide transit connectivity for landing-zone virtual networks across Azure regions. ", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", + "services": [ + "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "0e7c28ec-9366-4572-83b0-f4664b1d944a", "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": [ + "VNet", + "ExpressRoute", + "Entra" + ], "severity": "Medium", "subcategory": "Hub and spoke", - "text": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits and the maximum number of prefixes that can be advertised via ExpressRoute" + "text": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits and the maximum number of prefixes that can be advertised via ExpressRoute", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", + "services": [ + "VNet" + ], "severity": "High", "subcategory": "Hub and spoke", - "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings" + "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", + "services": [ + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", + "services": [ + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", + "services": [ + "VPN", + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", + "services": [ + "Cost", + "ExpressRoute" + ], + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", + "services": [ + "Cost", + "ExpressRoute" + ], + "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", + "services": [ + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", "link": "https://learn.microsoft.com/azure/networking/", + "services": [ + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", + "services": [ + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", + "services": [ + "VPN" + ], "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/" + "training": "https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "fe237de1-43b1-46c3-8d7a-a9b64704489a", - "link": "https://learn.microsoft.com/azure/networking/", - "severity": "Medium", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", + "services": [ + "Cost", + "ExpressRoute" + ], + "severity": "High", "subcategory": "Hybrid", - "text": "Use ExpressRoute Global Reach to connect large offices, regional headquarters, or datacenters connected to Azure via ExpressRoute.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", + "services": [ + "ExpressRoute" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b30e38c3-f298-412b-8363-cefe179b599d", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", + "services": [ + "Monitor", + "ExpressRoute" + ], "severity": "Medium", "subcategory": "Hybrid", "text": "Monitor ExpressRoute availability and utilization using built-in Azure Monitor metrics.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", + "services": [ + "ACR", + "Monitor", + "NetworkWatcher" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", + "services": [ + "ExpressRoute" + ], "severity": "Medium", "subcategory": "Hybrid", - "text": "Don't explicitly use ExpressRoute circuits from a single peering location. Doing so creates a single point of failure and makes the organization susceptible to peering location outages.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/" + "text": "Use ExpressRoute circuits from different peering locations for redundancy.", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sync-staging-server", + "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", + "services": [ + "ASR" + ], "severity": "Medium", "subcategory": "Hybrid", - "text": "When deploying an AD Connect VM, consider having a staging sever for high availability / Disaster recovery" + "text": "When deploying an AD Connect VM, consider having a staging sever for high availability / Disaster recovery", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", - "link": "https://learn.microsoft.com/en-us/azure/bastion/bastion-overview", - "severity": "Medium", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", + "services": [ + "VM" + ], + "severity": "High", "subcategory": "Hybrid", - "text": "Consider using Bastion to securely connect to your network." + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "558fd772-49b8-4211-82df-27ee412e7f98", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", - "severity": "Medium", + "services": [ + "ACR", + "VNet" + ], + "severity": "High", "subcategory": "IP plan", - "text": "Ensure no overlapping IP address spaces across Azure regions and on-premises locations", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", - "severity": "Medium", + "services": [ + "VNet" + ], + "severity": "Low", "subcategory": "IP plan", - "text": "Ensure to use IP addresses from the address allocation for private internets (RFC 1918).", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", - "severity": "Medium", + "services": [ + "VNet" + ], + "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/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e984a859-c773-4e7d-8616-23a765a917e1", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", - "severity": "Medium", - "subcategory": "IP plan", - "text": "Ensure no public IP address range (CIDR block) for VNETs, especially if not owned by your organization", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "waf": "Performance" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", - "severity": "Medium", + "services": [ + "VNet" + ], + "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/" + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "services": [ + "VNet", + "DNS" + ], "severity": "Medium", "subcategory": "IP plan", - "text": "For environments where name resolution in Azure is all that's required, use Azure Private DNS for resolution. Create a delegated zone for name resolution (such as 'azure.contoso.com').", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", + "services": [ + "ACR", + "VNet", + "DNS" + ], "severity": "Medium", "subcategory": "IP plan", - "text": "For environments where name resolution across Azure and on-premises is required, use existing DNS infrastructure (for example, Active Directory integrated DNS) deployed onto at least two virtual machines (VMs). Configure DNS settings in virtual networks to use those DNS servers.", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", - "severity": "Medium", + "services": [ + "VNet", + "DNS" + ], + "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." + "text": "Special workloads that require and deploy their own DNS (such as Red Hat OpenShift) should use their preferred DNS solution.", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "614658d3-558f-4d77-849b-821112df27ee", "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", - "severity": "Medium", + "services": [ + "VNet", + "VM", + "DNS" + ], + "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/" + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "1e43a58a-9c22-499c-9d7b-57d0c655562f", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", + "services": [ + "Bastion" + ], "severity": "Medium", - "subcategory": "Inspection", - "text": "Use Network Watcher packets to capture despite the limited capture window.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/" + "subcategory": "Internet", + "text": "Consider using Azure Bastion to securely connect to your network.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a65498f6-dfe2-437d-b143-b16c31d7aa9b", - "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet", + "services": [ + "VNet", + "Bastion" + ], "severity": "Medium", - "subcategory": "Inspection", - "text": "Use partner solutions for scenarios that require deep packet inspection." + "subcategory": "Internet", + "text": "Use Azure Bastion in a subnet /26 or larger.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", "link": "https://learn.microsoft.com/azure/app-service/networking-features", - "severity": "Medium", + "services": [ + "Firewall" + ], + "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/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "graph": "resources | where type == 'microsoft.network/azurefirewalls' | project id,compliant=isnotnull(properties.firewallPolicy.id)", - "guid": "0f1ce16e-d301-4d6e-a72e-52e3611cc58b", - "link": "https://learn.microsoft.com/azure/firewall/", - "severity": "Medium", - "subcategory": "Internet", - "text": "Use Firewall Manager with Virtual WAN to deploy and manage Azure firewalls across Virtual WAN hubs or in hub virtual networks.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", "link": "https://learn.microsoft.com/azure/firewall/", + "services": [ + "ACR", + "AzurePolicy", + "RBAC", + "Firewall" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", "link": "https://learn.microsoft.com/azure/firewall/", - "severity": "Medium", + "services": [ + "Firewall" + ], + "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/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d15f512a-6549-48f6-bfe2-37de143b16c3", - "link": "https://learn.microsoft.com/azure/firewall/", - "severity": "Medium", - "subcategory": "Internet", - "text": "Use WAF within a landing-zone virtual network for protecting inbound HTTP/S traffic from the internet.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", + "services": [ + "ACR", + "FrontDoor", + "AzurePolicy", + "WAF" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "severity": "Medium", + "services": [ + "AppGW", + "FrontDoor", + "AzurePolicy", + "WAF" + ], + "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", - "severity": "Medium", + "services": [ + "VNet", + "WAF" + ], + "severity": "High", "subcategory": "Internet", - "text": "If partner NVAs 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/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", - "severity": "Medium", + "services": [ + "VNet", + "DDoS" + ], + "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "e504547c-2447-4ec6-9138-a7200f1ce16e", - "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", - "severity": "Medium", - "subcategory": "PaaS", - "text": "If you need private communication to PaaS services, consider the different options available.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-private-access-to-azure-services/" + "checklist": "Azure Landing Zone Review (old version)", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", + "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", + "services": [ + "Firewall", + "DNS" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", + "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "link": "https://learn.microsoft.com/azure/firewall/premium-features", + "services": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Use Azure Firewall Premium for additional security and protection.", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", + "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "link": "https://learn.microsoft.com/azure/firewall/premium-features", + "services": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection.", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", + "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", + "services": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Configure Azure Firewall IDPS mode to Deny for additional protection.", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", + "services": [ + "NVA", + "VWAN", + "VNet", + "Storage", + "Firewall" + ], + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", - "severity": "Medium", + "services": [ + "VNet" + ], + "severity": "High", "subcategory": "PaaS", - "text": "Azure PaaS services that have been injected into a virtual network still perform management plane operations by using public IP addresses. Ensure that this communication is not broken", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "services": [ + "PrivateLink" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "services": [ + "PrivateLink", + "ExpressRoute" + ], "severity": "Medium", "subcategory": "PaaS", - "text": "Access Azure PaaS services from on-premises via ExpressRoute private peering. This method avoids transiting over the public internet.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "65498f6d-fe23-47de-843b-16c31d7aa9b6", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", - "severity": "Medium", - "subcategory": "PaaS", - "text": "Use virtual network service endpoints when Private Link isn't available", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "services": [ + "VNet" + ], "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" + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", "link": "https://learn.microsoft.com/azure/app-service/networking-features", + "services": [ + "VNet", + "NVA", + "DNS" + ], "severity": "Medium", "subcategory": "PaaS", - "text": "Don't use virtual network service endpoints when there are data exfiltration concerns, unless you use NVA filtering.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn" + "text": "If using virtual network service endpoints, filter egress FQDNs on an NVA to prevent data exfiltration.", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "179b599d-e0d5-4973-ad4c-d21b088137f5", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", - "severity": "Medium", - "subcategory": "PaaS", - "text": "Don't implement forced tunneling to enable communication from Azure to Azure resources.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn" + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", + "services": [ + "VNet", + "Firewall" + ], + "severity": "High", + "subcategory": "Segmentation", + "text": "Use a /26 prefix for your Azure Firewall subnets.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", + "services": [ + "VNet", + "VPN", + "ExpressRoute" + ], + "severity": "High", + "subcategory": "Segmentation", + "text": "Use at least a /27 prefix for your Gateway subnets", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", + "services": [ + "VNet" + ], "severity": "Medium", "subcategory": "Segmentation", - "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity." + "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity.", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", + "services": [ + "VNet" + ], "severity": "Medium", "subcategory": "Segmentation", "text": "Delegate subnet creation to the landing zone owner. ", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "ACR", + "VNet" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", + "services": [ + "VNet", + "VM" + ], "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", "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/" + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "dfe237de-143b-416c-91d7-aa9b64704489", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "services": [ + "VNet", + "NetworkWatcher" + ], "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/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a8042d88-e79d-417b-93b2-2a5a67e7a8ed", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", - "severity": "Medium", - "subcategory": "Segmentation", - "text": "Use NSGs to selectively allow connectivity between landing zones.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/" - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "4b30e38c-3f29-4812-a236-3cefe179b599", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", - "severity": "Medium", - "subcategory": "Segmentation", - "text": "For Virtual WAN topologies, route traffic across landing zones via Azure Firewall if the organization requires filtering and logging capabilities for traffic flowing across landing zones.", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", + "waf": "Security" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", + "services": [ + "VWAN" + ], "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/" + "training": "https://learn.microsoft.com/learn/modules/introduction-azure-virtual-wan/", + "waf": "Operations" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "services": [ + "ACR", + "VWAN" + ], "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." - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "4f5664b5-e984-4a85-ac77-3e7d261623a7", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Use Virtual Hub Routing features to further segment traffic between VNets and branches." - }, - { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "65a917e1-f348-4ef2-94c2-7d42e8bbac75", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", - "severity": "Medium", - "subcategory": "Virtual WAN", - "text": "Connect Virtual WAN hubs to on-premises datacenters by using ExpressRoute", - "training": "https://learn.microsoft.com/learn/modules/configure-expressroute-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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "71559ab9-153e-4890-aae2-8c84c33b6b78", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", - "severity": "Medium", + "services": [ + "ACR", + "VWAN" + ], + "severity": "Low", "subcategory": "Virtual WAN", - "text": "Connect branches and remote locations to the nearest Virtual WAN hub via Site-to-Site VPN, or enable branch connectivity to Virtual WAN via an SD-WAN partner solution.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-hybrid-networking/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "08b9fe5c-4104-49d4-83a9-23c3474d0001", + "checklist": "Azure Landing Zone Review (old version)", + "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", + "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "services": [ + "VWAN", + "Firewall" + ], "severity": "Medium", "subcategory": "Virtual WAN", - "text": "Connect users to the Virtual WAN hub via a Point-to-Site VPN.", - "training": "https://learn.microsoft.com/learn/modules/design-implement-hybrid-networking/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "services": [ + "VWAN" + ], "severity": "Medium", "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" + "text": "Ensure that the network architecture is within the Azure Virtual WAN limits.", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", + "services": [ + "Monitor", + "VWAN" + ], "severity": "Medium", "subcategory": "Virtual WAN", - "text": "For outbound Internet traffic protection and filtering, deploy Azure Firewall", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "12df27ee-412e-47f9-a3f6-304722dd69c5", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", + "services": [ + "VWAN" + ], "severity": "Medium", "subcategory": "Virtual WAN", - "text": "When deploying partner networking technologies and NVAs in VWAN, verify configuration with partner vendor's guidance to ensure there are no conflicting configurations" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "b5c2622f-54b6-49ba-b33a-ad5e8c68e1d7", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", + "services": [ + "VPN", + "VWAN", + "ExpressRoute" + ], "severity": "Medium", "subcategory": "Virtual WAN", - "text": "Ensure that Azure Virtual WAN and Azure Firewall resources are created in the connectivity subscription." + "text": "Use AS-Path as hub routing preference, since it is more flexible than ExpressRoute or VPN.", + "waf": "Reliability" }, { "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", + "services": [ + "VWAN" + ], "severity": "Medium", "subcategory": "Virtual WAN", - "text": "Ensure that the network architecture is within the Azure Virtual WAN limits." + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", - "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", - "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." - }, - { - "category": "Network Topology and Connectivity ", - "checklist": "Azure Landing Zone Review", - "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", - "link": "https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", + "checklist": "Azure Landing Zone Review (old version)", + "guid": "9c75dfef-573c-461c-a698-68598595581a", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", + "services": [ + "VWAN" + ], "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." + "subcategory": "Virtual WAN", + "text": "Assign enough IP space to virtual hubs, ideally a /23 prefix.", + "waf": "Reliability" }, { "category": "Operations", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", + "services": [ + "FrontDoor", + "Cost", + "AKV" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Use managed TLS certificates with Azure Front Door. Reduce operational cost and risk of outages due to certificate renewals." - }, - { - "category": "Operations", - "checklist": "Azure Landing Zone Review", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", - "severity": "Medium", - "subcategory": "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." + "subcategory": "App delivery", + "text": "Use managed TLS certificates with Azure Front Door. Reduce operational cost and risk of outages due to certificate renewals.", + "waf": "Operations" }, { "category": "Operations", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "Medium", - "subcategory": "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." + "subcategory": "App delivery", + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", + "services": [ + "FrontDoor" + ], "severity": "High", - "subcategory": "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." + "subcategory": "App delivery", + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", + "services": [ + "FrontDoor" + ], "severity": "Medium", - "subcategory": "Front Door", - "text": "Use HTTP to HTTPS redirection with Azure Front Door. Support older clients by redirecting them to an HTTPS request automatically." + "subcategory": "App delivery", + "text": "Use HTTP to HTTPS redirection with Azure Front Door. Support older clients by redirecting them to an HTTPS request automatically.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks." + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections." + "subcategory": "App delivery", + "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests." + "subcategory": "App delivery", + "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks." + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Front Door", - "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots." + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "Medium", - "subcategory": "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." + "subcategory": "App delivery", + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "Medium", - "subcategory": "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." + "subcategory": "App delivery", + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", "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" + ], "severity": "Medium", - "subcategory": "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. " + "subcategory": "App delivery", + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "Low", - "subcategory": "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." + "subcategory": "App delivery", + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "Medium", - "subcategory": "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." + "subcategory": "App delivery", + "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": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy" + ], "severity": "High", "subcategory": "Governance", - "text": "Leverage Azure Policy" + "text": "Leverage Azure Policy", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", + "services": [ + "AzurePolicy" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Identify required Azure tags and use the append policy mode to enforce usage." + "text": "Identify required Azure tags and use the append policy mode to enforce usage.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy", + "RBAC" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments." + "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "223ace8c-b123-408c-a501-7f154e3ab369", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy", + "Subscriptions" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Establish Azure Policy definitions at the top-level root management group so that they can be assigned at inherited scopes" + "text": "Establish Azure Policy definitions at the top-level root management group so that they can be assigned at inherited scopes", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "3829e7e3-1618-4368-9a04-77a209945bda", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required" + "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "43334f24-9116-4341-a2ba-527526944008", "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", + "services": [ + "AzurePolicy", + "Subscriptions" + ], "severity": "Low", "subcategory": "Governance", - "text": "Use Azure Policy to control which services users can provision at the subscription/management group level" + "text": "Use Azure Policy to control which services users can provision at the subscription/management group level", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Use built-in policies where possible to minimize operational overhead." + "text": "Use built-in policies where possible to minimize operational overhead.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", + "services": [ + "AzurePolicy", + "Subscriptions", + "RBAC", + "Entra" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Assign the built-in Policy Contributor role at a particular scope to enable application-level governance." + "text": "Assign the built-in Resource Policy Contributor role at a particular scope to enable application-level governance.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "19048384-5c98-46cb-8913-156a12476e49", "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "services": [ + "AzurePolicy", + "Subscriptions" + ], "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." + "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": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", + "services": [ + "AzurePolicy", + "VM" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Use Azure policies to automatically deploy software configurations through VM extensions and enforce a compliant baseline VM configuration." + "text": "Use Azure policies to automatically deploy software configurations through VM extensions and enforce a compliant baseline VM configuration.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", "link": "Configure Azure Automation Start/Stop VMs during off-hours | Microsoft Learn", + "services": [ + "Cost", + "VM" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Consider using automation tags to start/stop VM's in your environment to save on cost." + "text": "Consider using automation tags to start/stop VM's in your environment to save on cost.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", + "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", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", + "services": [ + "AzurePolicy", + "Monitor", + "VM" + ], "severity": "Medium", "subcategory": "Governance", - "text": "Monitor VM security configuration drift via Azure Policy." + "text": "Monitor VM security configuration drift via Azure Policy.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "5017f154-e3ab-4369-9829-e7e316183687", "link": "https://learn.microsoft.com/azure/key-vault/general/overview", + "services": [ + "AKV" + ], "severity": "High", "subcategory": "Secrets", - "text": "Use Azure Key Vault to store your secrets and credentials" + "text": "Use Azure Key Vault to store your secrets and credentials", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "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", "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", + "services": [ + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets." + "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, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AzurePolicy", + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." + "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "dc055bcf-619e-48a1-9f98-879525d62688", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "RBAC", + "Entra", + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Follow a least privilege model by limiting authorization to permanently delete keys, secrets, and certificates to specialized custom Azure Active Directory (Azure AD) roles." + "text": "Follow a least privilege model by limiting authorization to permanently delete keys, secrets, and certificates to specialized custom Azure Active Directory (Azure AD) roles.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Automate the certificate management and renewal process with public certificate authorities to ease administration." + "text": "Automate the certificate management and renewal process with public certificate authorities to ease administration.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "913156a1-2476-4e49-b541-acdce979377b", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Establish an automated process for key and certificate rotation." + "text": "Establish an automated process for key and certificate rotation.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "VNet", + "PrivateLink", + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Enable firewall and virtual network service endpoint or private endpoint on the vault to control access to the key vault." + "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, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", + "services": [ + "Monitor", + "Entra", + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Use the platform-central Azure Monitor Log Analytics workspace to audit key, certificate, and secret usage within each instance of Key Vault." + "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, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AzurePolicy", + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Delegate Key Vault instantiation and privileged access and use Azure Policy to enforce a consistent compliant configuration." + "text": "Delegate Key Vault instantiation and privileged access and use Azure Policy to enforce a consistent compliant configuration.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "16183687-a047-47a2-8994-5bda43334f24", "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", + "services": [ + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "91163418-2ba5-4275-8694-4008be7d7e48", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "text": "Use an Azure Key Vault per application per environment per region." + "text": "Use an Azure Key Vault per application per environment per region.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "25d62688-6d70-4ba6-a97b-e99519048384", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "ACR", + "ASR", + "AKV" + ], "severity": "Medium", "subcategory": "Secrets", - "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." + "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, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", + "services": [ + "Entra" + ], "severity": "Medium", "subcategory": "Security", - "text": "Use Azure AD reporting capabilities to generate access control audit reports." + "text": "Use Azure AD reporting capabilities to generate access control audit reports.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", + "services": [ + "Storage", + "ARS", + "Monitor" + ], "severity": "Medium", "subcategory": "Security", - "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." + "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" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "09945bda-4333-44f2-9911-634182ba5275", "link": "https://learn.microsoft.com/azure/security-center/", + "services": [ + "Subscriptions", + "Defender" + ], "severity": "Medium", "subcategory": "Security", - "text": "Enable Defender for Cloud Standard for all subscriptions." + "text": "Enable Defender for Cloud Standard for all subscriptions.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", "link": "https://learn.microsoft.com/azure/security-center/", + "services": [ + "Defender", + "Monitor" + ], "severity": "Medium", "subcategory": "Security", - "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud." + "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "services": [ + "Monitor", + "Entra" + ], "severity": "Medium", "subcategory": "Security", - "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace." + "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", + "services": [], "severity": "Medium", "subcategory": "Security", - "text": "Determine the incident response plan for Azure services before allowing it into production." + "text": "Determine the incident response plan for Azure services before allowing it into production.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "01365d38-e43f-49cc-ad86-8266abca264f", "link": "https://www.microsoft.com/security/business/zero-trust", + "services": [], "severity": "Medium", "subcategory": "Security", - "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate." + "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate.", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", + "services": [], "severity": "Medium", "subcategory": "Security", - "text": "Plan how new azure services will be implemented" + "text": "Plan how new azure services will be implemented", + "waf": "Security" }, { "category": "Security, Governance and Compliance", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", + "services": [], "severity": "Medium", "subcategory": "Security", - "text": "Plan how service request will be fulfilled for Azure services" + "text": "Plan how service request will be fulfilled for Azure services", + "waf": "Security" }, { "category": "Security, Governance and Compliance ", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", + "services": [], "severity": "High", "subcategory": "Governance", - "text": "It is recommended to follow Microsoft Best Practice Naming Standards" + "text": "It is recommended to follow Microsoft Best Practice Naming Standards", + "waf": "Security" }, { "category": "Security, Governance and Compliance ", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", - "link": "https://learn.microsoft.com/en-us/azure/storage/common/storage-require-secure-transfer", + "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Security", - "text": "Secure transfer to storage accounts should be enabled" + "text": "Secure transfer to storage accounts should be enabled", + "waf": "Security" }, { "category": "Security, Governance and Compliance ", - "checklist": "Azure Landing Zone Review", + "checklist": "Azure Landing Zone Review (old version)", "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", - "link": "https://learn.microsoft.com/en-us/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", + "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", + "services": [ + "Storage" + ], "severity": "High", "subcategory": "Security", - "text": "Enable container soft delete for the storage account to recover a deleted container and its contents." - }, - { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "41177955-fe8f-430b-ae72-20dc5b6880da", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/overview", - "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." + "text": "Enable container soft delete for the storage account to recover a deleted container and its contents.", + "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", - "severity": "High", - "subcategory": "Business", - "text": "Define your tenants. Understand how many tenants you will support initially, and your growth plans." + "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" + ], + "severity": "Medium", + "subcategory": "Physical", + "text": "All planned storage pools should use direct-attached storage (SATA, SAS, NVMe)", + "waf": "Performance" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "a2111b8b-cc66-4aa2-9da6-c09fa23851b6", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/pricing-models", - "severity": "High", - "subcategory": "Business", - "text": "Define your pricing model and ensure it aligns with your tenants' consumption of Azure resources." + "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": [ + "ACR", + "Storage" + ], + "severity": "Medium", + "subcategory": "Physical", + "text": "Disks are symmetrical across all nodes", + "waf": "Performance" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "331e84a6-2d65-4359-92ff-a1870b062995", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/pricing-models", + "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": [ + "Storage", + "Backup" + ], "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": "S2D", + "text": "Parity type disk redundancy should only be used for low I/O volumes (backup/archive)", + "waf": "Performance" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "90516b37-aab1-46ca-95bb-cc14a6a1608b", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenancy-models", + "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" + ], "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": "S2D", + "text": "Ensure there at least 2 capacity disks with available capacity in the Storage Pool", + "waf": "Reliability" }, { - "category": "Business", - "checklist": "Multitenant architecture", - "guid": "f5d76ae1-7048-4ff5-abba-f1ca799578b9", - "link": "https://learn.microsoft.com/azure/marketplace/plan-saas-offer", - "severity": "Medium", - "subcategory": "Business", - "text": "When you're ready, sell your B2B multitenant solution using the Microsoft Commercial Marketplace." + "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": [ + "Storage" + ], + "severity": "Low", + "subcategory": "S2D", + "text": "'Delimited allocation' has been considered to improve volume resiliency in a multi-node failure", + "waf": "Reliability" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "9e7cedd9-1e05-4aeb-a7b3-01fe695a394c", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/design-checklist", - "severity": "High", - "subcategory": "Reliability", - "text": "Review the Azure Well-Architected Reliability checklist, which is applicable to all workloads." + "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" + ], + "severity": "Medium", + "subcategory": "S2D", + "text": "CSVs are created in multiples of node count", + "waf": "Performance" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "e9521a55-2a7c-425c-8f3e-c38fd0c4df75", - "link": "https://learn.microsoft.com/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor", - "severity": "High", - "subcategory": "Reliability", - "text": "Understand the Noisy Neighbor antipattern. Prevent individual tenants from impacting the system's availability for other tenants." + "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": "Reliability", - "checklist": "Multitenant architecture", - "guid": "2b99cb00-9abb-49b6-b11c-f2af9692f09e", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/overview", + "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" + ], "severity": "Medium", - "subcategory": "Reliability", - "text": "Design your multitenant solution for the level of growth that you expect. But don't overengineer for unrealistic growth." + "subcategory": "S2D", + "text": "A minimum of 1 type of each disk type per node has been factored as a reserve disk", + "waf": "Reliability" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "7a634a0e-1c9d-42b1-aac2-5a5378f103f1", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/business-metrics", - "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": "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": [ + "Storage" + ], + "severity": "Low", + "subcategory": "S2D", + "text": "VMFleet has been run prior to workload deployment to baseline storage performance", + "waf": "Performance" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "45beeeaf-fc59-4079-8fca-65d5724abaa7", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", - "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": "Storage", + "checklist": "Azure Stack HCI Review", + "guid": "13c12e2a-c938-4dd1-9223-507d5e17f9c5", + "id": "01.03.01", + "services": [ + "Storage" + ], + "severity": "Medium", + "subcategory": "Host OS", + "text": "OS drives use a dedicated storage controller", + "waf": "Reliability" }, { - "category": "Reliability", - "checklist": "Multitenant architecture", - "guid": "2ff55551-984b-4606-95eb-bfb9c8b36761", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", + "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": [ + "Storage" + ], "severity": "Medium", - "subcategory": "Reliability", - "text": "Apply chaos engineering principles to test the reliability of your solution." + "subcategory": "Host OS", + "text": "CSV in-memory read caching is enabled and properly configured", + "waf": "Performance" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "8238c038-8eb2-4a02-8bd5-4908c9442c1c", - "link": "https://learn.microsoft.com/security/zero-trust", - "severity": "High", - "subcategory": "Security", - "text": "Apply the Zero Trust and least privilege principles in all layers of your solution." + "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": [ + "ACR" + ], + "severity": "Medium", + "subcategory": "Host", + "text": "NICs are symmetrical across nodes", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "92160e00-6894-4102-97e0-615d4ed93c01", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/map-requests", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "ea8054db-a558-4533-80c8-5d9cf447ba19", + "id": "02.01.02", + "services": [ + "Storage" + ], "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." + "subcategory": "Host", + "text": "Storage networking is redundant", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "3c1538b4-5676-4b85-b451-432befb37b4f", - "link": "https://learn.microsoft.com/azure/security/fundamentals/pen-testing", + "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": "Security", - "text": "Perform ongoing penetration testing and security code reviews." + "subcategory": "Host", + "text": "Host networking configuration is managed by Network ATC and intents are healthy", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "5fca45ce-cf2d-42c0-a62c-aac92ba31498", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/governance-compliance", - "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." + "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": "Security", - "checklist": "Multitenant architecture", - "guid": "30adb90d-83d4-4a2e-986e-327ffe04e7a5", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/domain-names", - "severity": "High", - "subcategory": "Security", - "text": "Correctly manage domain names and avoid vulnerabilities like dangling DNS and subdomain takeover attacks." + "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": [ + "VNet", + "Storage" + ], + "severity": "Medium", + "subcategory": "Host", + "text": "Storage NICs are assigned static IP addresses on separate subnets and VLANs", + "waf": "Reliability" }, { - "category": "Security", - "checklist": "Multitenant architecture", - "guid": "72ded36d-c633-4e0d-bd41-799a29da3481", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/service/overview", + "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": "Security", - "text": "Follow service-specific guidance for multitenancy." + "subcategory": "Host", + "text": "For switchless designs, dual link full mesh connectivity has been implemented", + "waf": "Reliability" }, { - "category": "Cost Optimization", - "checklist": "Multitenant architecture", - "guid": "db30a9fc-9b1d-40f3-ab90-01f6a3e87fc8", - "link": "https://learn.microsoft.com/azure/architecture/framework/cost/design-checklist", + "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": [ + "Storage" + ], "severity": "Medium", - "subcategory": "Cost Optimization", - "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." + "subcategory": "Host", + "text": "If the cluster is made up of more than 3 nodes, a switched storage network has been implemented", + "waf": "Reliability" }, { - "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": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "603c6d71-59d2-419c-a312-8edc6e799c6a", + "id": "02.01.08", + "services": [ + "Storage" + ], "severity": "High", - "subcategory": "Cost Optimization", - "text": "Ensure you can adequately measure per-tenant consumption and correlate it with your infrastructure costs." + "subcategory": "Host", + "text": "RDMA is enabled on the Storage networking", + "waf": "Performance" }, { - "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": "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": "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": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "0d475a5a-2c0f-47ab-b1e1-701da68d3407", - "link": "https://learn.microsoft.com/azure/architecture/checklist/data-ops", - "severity": "High", - "subcategory": "Operational Excellence", - "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." + "subcategory": "Host", + "text": "Test-RDMA.ps1 has been run to validate the RDMA configuration", + "waf": "Performance" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "9f7fa7a9-47fc-4f04-81f6-9f9e87571ed3", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/tenant-lifecycle", + "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": [ + "VM" + ], "severity": "Medium", - "subcategory": "Operational Excellence", - "text": "Use automation to manage the tenant lifecycle, such as onboarding, deployment, provisioning, and configuration." + "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": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "e0bfceed-4f4e-492d-b9f5-898815faa363", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/updates", + "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": [ + "VM" + ], "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": "SDN", + "text": "There are at least 5 Network Controller VMs deployed", + "waf": "Reliability" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "a3f80518-d428-4c02-b2cc-dfaef47db7e2", + "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": [ + "Backup" + ], "severity": "High", - "subcategory": "Operational Excellence", - "text": "Monitor the health of the overall system, as well as each tenant." + "subcategory": "SDN", + "text": "Backups of SDN infrastructure are configured and tested", + "waf": "Operations" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "dfb42da5-f871-4953-9e5c-da6fda3f1411", + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "51eaa4b6-b9a7-43e1-a7dc-634d3107bc6d", + "id": "03.01.01", + "services": [ + "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." + "subcategory": "Cluster", + "text": "SCOM Managed Instance has been considered for more complex monitoring and alerting scenarios", + "waf": "Operations" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "c0c72a1b-e34d-4b3d-b808-2e49f51ce47e", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/resource-organization", + "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": [ + "Monitor" + ], "severity": "High", - "subcategory": "Operational Excellence", - "text": "Organize your Azure resources for isolation and scale." + "subcategory": "Cluster", + "text": "Alerts have been configured for the cluster, either using Azure Monitor, SCOM, or a third-party solution", + "waf": "Operations" }, { - "category": "Operational Excellence", - "checklist": "Multitenant architecture", - "guid": "c5c5e22d-4b51-4cac-a980-f7aac1a4b427", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/deployment-configuration", + "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": "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." + "subcategory": "Cluster", + "text": "Insights has been enabled at the cluster level and all nodes are reporting data", + "waf": "Operations" }, { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "f0b1fbd8-689c-4ab3-be1d-ad7607d2fbfd", - "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/performance-efficiency", - "severity": "High", - "subcategory": "Performance Efficiency", - "text": "Review the Azure Well-Architected Performance Efficiency checklist, which is applicable to all workloads." + "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": [ + "Monitor" + ], + "severity": "Medium", + "subcategory": "Cluster", + "text": "Azure Monitoring Agent has been deployed to hosts and an appropriate Data Collection Rule has been configured", + "waf": "Operations" }, { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "18911c4c-934c-49a8-839a-60c092afce30", - "link": "https://learn.microsoft.com/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor", - "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." + "category": "Management and Monitoring", + "checklist": "Azure Stack HCI Review", + "guid": "6143af1d-0d1a-4163-b1c9-662f7459bb98", + "id": "03.02.01", + "services": [ + "Monitor" + ], + "severity": "Medium", + "subcategory": "Hardware", + "text": "Relevant hardware monitoring has been configured", + "waf": "Operations" }, { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "6acf7eb5-24a3-47c7-ae87-1196cd96048e", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", + "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": [ + "Monitor" + ], "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": "Hardware", + "text": "Relevant hardware alerting has been configured", + "waf": "Operations" }, { - "category": "Performance Efficiency", - "checklist": "Multitenant architecture", - "guid": "ea55400d-f97d-45aa-b71b-34224bf91ed4", - "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/resource-organization", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "c0da5bbd-0f0d-4a26-98ec-38c9cc42b323", + "id": "04.01.01", + "services": [ + "VM" + ], + "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": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "a8ecf23c-c048-4fa9-b87b-51ebfb409863", + "id": "04.01.02", + "services": [ + "VM" + ], + "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": "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": [ + "ASR", + "Backup", + "VM" + ], "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." + "subcategory": "VM", + "text": "Backups of HCI VMs have been configured using MABS or a third-party solution", + "waf": "Operations" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "48f7ae57-1035-4101-8a38-fbe163d03e8a", + "id": "06.01.01", + "services": [], "severity": "High", - "subcategory": "Identity", - "text": "Enforce a RBAC model for management groups, subscriptions, resource groups and resources", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "subcategory": "Cluster Configuration", + "text": "Cluster configuration or a configuration script has been documented and maintained", + "waf": "Operations" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "45911475-e39e-4530-accc-d979366bcda2", + "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": "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": "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/learn/modules/plan-implement-administer-conditional-access/" + "subcategory": "Cluster Configuration", + "text": "Cluster-Aware Updating has been configured for Windows and hardware updates (if available)", + "waf": "Operations" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", + "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": "Identity", - "text": "Implement Single Sign on (SSO) using Azure Active Directory or Active Directory Federation Services (AD FS) for end users to con nect to SAP applications where possible.", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/" + "subcategory": "Cluster Configuration", + "text": "Cluster validation has been run against the configured cluster", + "waf": "Reliability" }, { - "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-successfactors-inbound-provisioning-cloud-only-tutorial", + "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": [ + "VM" + ], "severity": "Medium", - "subcategory": "Identity", - "text": "If SuccessFactor is used as HCM application leverage the automated user provisioning feature to Azure AD.", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/" + "subcategory": "Cluster Configuration", + "text": "Azure Benefits has been enabled at the cluster and VM levels", + "waf": "Cost" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "f7c95f06-e154-4e3a-a359-2829e6e20617", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", + "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": "Identity", - "text": "SSO to SAP Netweaver based web applications like Fiori, webgui etc. can be implemented using SAML", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/" + "subcategory": "Cluster Configuration", + "text": "The Environment Checker module has been run to validate the environment", + "waf": "Reliability" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "3686af46-791f-4893-9ada-43324e138115", - "link": "https://learn.microsoft.com/azure/active-directory-b2c/user-overview", - "severity": "High", - "subcategory": "Identity", - "text": "SSO to SAP GUI can be implemented using either SAP SSO or a 3rd party solution", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/" - }, - { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "23181aa4-1742-4694-9ff8-ae7d7d474317", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", + "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": [ + "AzurePolicy" + ], "severity": "Medium", - "subcategory": "Identity", - "text": "SSO to SAP SaaS applications like SAP Analytics Cloud, SAP Cloud Platform, SAP Cloud Platform IAS and SAP C4C with Azure AD can be implemented using SAML", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/" + "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": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "6c8bcbf4-5bbe-4609-b8a0-3e97778424d6", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access", + "category": "Operations", + "checklist": "Azure Stack HCI Review", + "guid": "e6a3f3a7-4a7d-49e2-985a-6e39dd284027", + "id": "06.02.02", + "services": [], "severity": "Medium", - "subcategory": "Identity", - "text": " ", - "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/" + "subcategory": "Cluster Configuration", + "text": "WAC is on the latest release and configured to automatically upgrade extensions", + "waf": "Reliability" }, { - "category": "Identity and Access", - "checklist": "Azure Landing Zone Review", - "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", + "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": [ + "Entra" + ], "severity": "Medium", - "subcategory": "Identity", - "text": " ", - "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/" + "subcategory": "Stretch Clustering", + "text": "There is sub 5ms latency between each site if synchronous replication is being configured AAD", + "waf": "Performance" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "enforce existing Management Group policies to SAP Subscriptions", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "3277558e-3155-4088-b49a-78594cb4ce1a", + "id": "07.01.02", + "services": [ + "VNet", + "Storage" + ], + "severity": "High", + "subcategory": "Stretch Clustering", + "text": "Management, Replication and Storage networks excluded from stretched VLANs configurations, are routed, and in different subnets", + "waf": "Reliability" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "enfore closely closely coupled applications into the same SAP Subscription to avoid additional routing and management complexity", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "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", + "waf": "Operations" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "category": "Networking", + "checklist": "Azure Stack HCI Review", + "guid": "8e62945f-b9ac-4a5c-a4e4-836f527010b4", + "id": "07.02.02", + "services": [ + "ACR" + ], "severity": "Medium", - "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/learn/paths/enterprise-scale-architecture/" + "subcategory": "Stretch Clustering", + "text": "Separate vLANs and networks are used for each replication network across both sites", + "waf": "Reliability" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medium", - "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/learn/paths/enterprise-scale-architecture/" + "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": [ + "Storage" + ], + "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" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medium", - "subcategory": "Subscriptions", - "text": "Ensure required services and features are available within the chosen deployment regions eg. ANF , Zone etc.", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "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": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "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)" + "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": [ + "Storage" + ], + "severity": "High", + "subcategory": "Stretch Clustering", + "text": "Storage backing log volumes must be faster (ideally) or at least as fast as capacity storage", + "waf": "Reliability" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "7d474317-6c8b-4cbf-95bb-e609d8a03e97", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "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": [ + "ASR", + "Backup" + ], "severity": "Medium", - "subcategory": "Subscriptions", - "text": " " + "subcategory": "Disaster Recovery", + "text": "Azure Site Recovery has been considered for DR purposes", + "waf": "Operations" }, { - "category": "Management Group and Subscriptions", - "checklist": "Azure Landing Zone Review", - "guid": "778424d6-1678-45d6-ba96-c96ad88518f4", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "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": "Subscriptions", - "text": " " + "subcategory": "Host", + "text": "BitLocker has been enabled on CSVs for volume encryption, where appropriate", + "waf": "Security" }, { - "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 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": "IP plan", - "text": "Public I.P assignment to VM running SAP Workload is not recommended.", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/" + "subcategory": "Host", + "text": "SMB encryption has been enabled, where appropriate", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "9cccd979-366b-4cda-8750-ab1ab039d95d", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", + "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", + "services": [ + "Defender" + ], "severity": "Medium", - "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": "Host", + "text": "Microsoft Defender Antivirus has been enabled on all nodes", + "waf": "Security" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "54c7c892-9cb1-407d-9325-ae525ba34d46", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", + "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": [], "severity": "Medium", - "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/" + "subcategory": "Host", + "text": "Credential Guard has been configured, where appropriate", + "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/virtual-networks-name-resolution-for-vms-and-role-instances", + "category": "Management", + "checklist": "Azure API Management Review", + "guid": "06862505-2d9a-4874-9491-2837b00a3475", + "link": "https://learn.microsoft.com/azure/api-management/backends", + "services": [ + "APIM" + ], "severity": "Medium", - "subcategory": "IP plan", - "text": "Ensure Accelerated Networking is enable for all VM where it is applicable.", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/" + "subcategory": "Best practices", + "text": "Use Backends feature to eliminate redundant API backend configurations" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "a3592829-e6e2-4061-9368-6af46791f893", - "link": "https://learn.microsoft.com/azure/networking/", + "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" + ], "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/learn/modules/design-implement-azure-expressroute/" + "subcategory": "Best practices", + "text": "Use Named Values to store common values that can be used in policies" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "5ada4332-4e13-4811-9231-81aa41742694", - "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", + "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", + "services": [ + "ASR", + "APIM" + ], "severity": "Medium", - "subcategory": "PaaS", - "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/learn/paths/implement-network-security/?source=learn" + "subcategory": "Business continuity and disaster recovery", + "text": "Deploy to multiple Azure regions" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "3ff8ae7d-7d47-4431-96c8-bcbf45bbe609", + "category": "Management", + "checklist": "Azure API Management Review", + "guid": "9c8d1664-dd9a-49d4-bd83-950af0af4044", + "link": "https://learn.microsoft.com/azure/api-management/high-availability", + "services": [ + "ASR", + "APIM" + ], "severity": "Medium", - "subcategory": "PaaS", - "text": "Ensure that internal deployments for Azure Load Balancer are set up to use Direct Server Return (DSR) for HA configuration on the DBMS layer" + "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": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d8a03e97-7784-424d-9167-85d6fa96c96a", - "link": "https://learn.microsoft.com/azure/app-service/networking-features", - "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/learn/paths/secure-networking-infrastructure/" + "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", + "services": [ + "ASR", + "APIM", + "Backup" + ], + "severity": "High", + "subcategory": "Business continuity and disaster recovery", + "text": "Ensure there is an automated backup routine" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "d88518f4-8273-44c8-a6ba-280214591147", - "link": "https://learn.microsoft.com/azure/firewall/", + "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", + "services": [ + "AzurePolicy", + "APIM" + ], "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.", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + "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": "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", - "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/" + "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", + "services": [ + "AzurePolicy", + "APIM", + "EventHubs" + ], + "severity": "Low", + "subcategory": "Performance and scalability", + "text": "If you need to log at high performance levels, consider Event Hubs policy" }, { - "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/ag/ag-overview", + "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", + "services": [ + "AzurePolicy", + "APIM" + ], "severity": "Medium", - "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/" + "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": "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", + "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", + "services": [ + "APIM" + ], "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/learn/paths/secure-application-delivery/" + "subcategory": "Performance and scalability", + "text": "Configure autoscaling to scale out the number of instances when the load increases" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "6e154e3a-a359-4282-ae6e-206173686af4", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/organize-resources?tabs=AzureManagementGroupsAndHierarchy", + "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", + "services": [ + "APIM" + ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "If Azure NetApp Files is used for SAP deployment , ensure that only one delegate subnet can exist in a Vnet for Azure NetAppFiles", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/" + "subcategory": "Performance and scalability", + "text": "Deploy self-hosted gateways where Azure doesn't have a region close to the backend APIs." }, { - "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": "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": [ + "AzurePolicy", + "APIM" + ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "Use NSGs and application security groups to micro-segment traffic within SAP application layer, like App subnet, DB subnet and Web subnet etc.", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/" + "subcategory": "Development best practices", + "text": "Implement an error handling policy at the global level" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "41742694-3ff8-4ae7-b7d4-743176c8bcbf", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", + "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": [ + "AzurePolicy", + "APIM" + ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "It is not supported to deploy any NVA between SAP application and SAP Database server", - "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/" + "subcategory": "Development best practices", + "text": "Ensure all APIs policies include a element." }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "45bbe609-d8a0-43e9-9778-424d616785d6", + "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" + ], "severity": "Medium", - "subcategory": "Segmentation", - "text": "Placing of the SAP application layer and SAP DBMS in different Azure VNets that aren't peered isn't supported" + "subcategory": "Development best practices", + "text": "Use Policy Fragments to avoid repeating same policies definitions across multiple APIs" }, { - "category": "Network Topology and Connectivity", - "checklist": "Azure Landing Zone Review", - "guid": "fa96c96a-d885-418f-9827-34c886ba2802", + "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": "Segmentation", - "text": "For optimal network latency with SAP applications, consider using Azure proximity placement groups." + "subcategory": "Monetization", + "text": "If you are planning to monetize your APIs, review the 'monetization support' article for best practices" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "14591147-5e39-4e53-89cc-cd979366bcda", - "severity": "Medium", + "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": [ + "APIM", + "Monitor" + ], + "severity": "High", "subcategory": "Monitoring", - "text": "Use SAP Solution Manager and Azure Monitor for SAP Solutions to monitor SAP HANA, high-availability SUSE clusters, and SQL systems" + "text": "Enable Diagnostics Settings to export logs to Azure Monitor" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "2750ab1a-b039-4d95-b54c-7c8929cb107d", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "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": [ + "APIM", + "Monitor" + ], "severity": "Medium", "subcategory": "Monitoring", - "text": "Run a VM Extension for SAP check. VM Extension for SAP uses the assigned managed identity of a virtual machine to access VM monitoring and configuration data.", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/" + "text": "Enable Application Insights for more detailed telemetry" }, { - "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", - "severity": "Medium", + "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": [ + "APIM", + "Monitor" + ], + "severity": "High", "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/" + "text": "Configure alerts on the most critical metrics" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "2f7c95f0-6e15-44e3-aa35-92829e6e2061", - "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Protect your HANA database with Azure Backup service. If you deploy Azure NetApp Files (ANF) for your HANA database, use the Azure Application Consistent Snapshot tool (AzAcSnap) to take application-consistent snapshots", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "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": [ + "APIM", + "Entra", + "AKV" + ], + "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": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "73686af4-6791-4f89-95ad-a43324e13811", - "link": "https://learn.microsoft.com/azure/automation/update-management/overview", - "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.", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/" + "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": [ + "APIM", + "Entra" + ], + "severity": "High", + "subcategory": "Identity", + "text": "Protect incoming requests to APIs (data plane) with Azure AD" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "523181aa-4174-4269-93ff-8ae7d7d47431", - "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", + "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": [ + "APIM", + "Entra" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Use Network Watcher Connection Monitor to monitor SAP database and application server latency metrics, or collect and display network latency measurements with Azure Monitor.", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/" + "subcategory": "Identity", + "text": "Use Azure AD to authenticate users in the Developer Portal" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "76c8bcbf-45bb-4e60-ad8a-03e97778424d", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", + "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": [ + "APIM", + "Entra" + ], "severity": "Medium", - "subcategory": "Monitoring", - "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/learn/paths/implement-resource-mgmt-security/" + "subcategory": "Privileged access", + "text": "Create appropriate groups to control the visibility of the products" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "616785d6-fa96-4c96-ad88-518f482734c8", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "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": [ + "VNet", + "APIM" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "For each Azure subscription, run an Azure Availability Zone latency test before zonal deployment to choose low-latency zones for SAP on Azure deployment." + "subcategory": "Security", + "text": "Deploy the service within a Virtual Network (VNET)" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "86ba2802-1459-4114-95e3-9e5309cccd97", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "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": [ + "VNet", + "APIM", + "Monitor" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Implement threat protection for SAP with Microsoft Sentinel." + "subcategory": "Security", + "text": "Deploy network security groups (NSG) to your subnets to restrict or monitor traffic" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "4d116785-d2fa-456c-96ad-48408fe72734", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "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": [ + "VNet", + "APIM", + "PrivateLink" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enforcing configuration of update management through policy ensures all VMs are included in the patch management regimen, provides application teams with the ability to manage patch deployment for their VMs, and provides central IT with visibility and enforcement capabilities across all VMs" + "subcategory": "Security", + "text": "Deploy Private Endpoints to filter incoming traffic when VNET is not used" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "c486ba28-0dc0-4591-af65-de8e1309cccd", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", - "severity": "Medium", - "subcategory": "Monitoring", - "text": "Enable VM Insights for VM's running SAP Workloads." + "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" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "579266bc-ca27-45fa-a1ab-fe9d55d04c3c", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", + "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": [ + "FrontDoor", + "APIM" + ], "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." + "subcategory": "Connectivity", + "text": "Use Azure Front Door for multi-region deployment" }, { - "category": "Management and Monitoring", - "checklist": "Azure Landing Zone Review", - "guid": "4919cb1b-3d13-425a-b124-ba34df685edd", - "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", + "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": [ + "APIM" + ], "severity": "Medium", - "subcategory": "Monitoring", - "text": " " + "subcategory": "Automation", + "text": "Simplify management with PowerShell automation scripts" }, { - "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", - "severity": "High", - "subcategory": "Secrets", - "text": "Use Azure Key Vault to store your secrets and credentials" + "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": [ + "APIM", + "Entra" + ], + "severity": "Medium", + "subcategory": "Best practices", + "text": "Review DevOps best practices from the Cloud Adaption Framework APIM Landing Zone Accelerator" }, { - "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": "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": [ + "APIM", + "Entra" + ], "severity": "Medium", - "subcategory": "Secrets", - "text": "It is recommended to LOCK the Azure Resources post successful deployment to safeguard against unauthorized changes" + "subcategory": "Best practices", + "text": "Promote usage of Visual Studio Code APIM extension for faster API development" }, { - "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": "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": [ + "APIM" + ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Provision Azure Key Vault with the soft delete and purge policies enabled to allow retention protection for deleted objects." + "subcategory": "DevOps", + "text": "Implement DevOps and CI/CD in your workflow" }, { - "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": "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" + ], "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" + "subcategory": "APIs", + "text": "Secure APIs using client certificate authentication" }, { - "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", - "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." + "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" + ], + "severity": "Medium", + "subcategory": "APIs", + "text": "Secure backend services using client certificate authentication" }, { - "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": "Security", + "checklist": "Azure API Management Review", + "guid": "074435f5-4a46-41ac-b521-d6114cb5d845", + "link": "https://learn.microsoft.com/azure/api-management/mitigate-owasp-api-threats", + "services": [ + "APIM" + ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Delegate an SAP admin custom role with just-in-time access." + "subcategory": "APIs", + "text": "Review 'Recommendations to mitigate OWASP API Security Top 10 threats' article and check what is applicable to your APIs" }, { - "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": "Security", + "checklist": "Azure API Management Review", + "guid": "5507c4b8-a7f8-41d6-9661-418c987100c9", + "link": "https://learn.microsoft.com/azure/api-management/authorizations-overview", + "services": [ + "APIM" + ], "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" + "subcategory": "APIs", + "text": "Use Authorizations feature to simplify management of OAuth 2.0 token for your backend APIs" }, { - "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", - "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" + "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", + "services": [ + "APIM" + ], + "severity": "High", + "subcategory": "Ciphers", + "text": "Use the latest TLS version when encrypting information in transit. Disable outdated and unnecessary protocols and ciphers when possible." }, { - "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", - "severity": "Medium", - "subcategory": "Secrets", - "text": "Make sure you harden the operating system to eradicate vulnerabilities that could lead to attacks on the SAP database." + "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", + "services": [ + "APIM", + "AKV" + ], + "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" }, { - "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": "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", + "services": [ + "APIM", + "Entra" + ], "severity": "Medium", - "subcategory": "Secrets", - "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required." + "subcategory": "Identities", + "text": "Use managed identities to authenticate to other Azure resources whenever possible" }, { - "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", - "severity": "Medium", - "subcategory": "Secrets", - "text": "Use an Azure Key Vault per application per environment per region." + "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", + "services": [ + "AppGW", + "APIM", + "Entra", + "WAF" + ], + "severity": "High", + "subcategory": "Network", + "text": "Use web application firewall (WAF) by deploying Application Gateway in front of APIM" }, { - "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", - "severity": "Medium", - "subcategory": "Secrets", - "text": " " + "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": [ + "Subscriptions", + "Defender" + ], + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Security Center/Defender enable in all subscriptions" }, { - "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": "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": [ + "Defender", + "Monitor" + ], "severity": "High", - "subcategory": "Governance", - "text": "Customize role-based access control (RBAC) roles for SAP on Azure spoke subscriptions to avoid accidental network-related changes" + "subcategory": "Pricing & Settings", + "text": "Security Center/Defender enabled on all Log Analytics workspaces" }, { - "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": "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": [ + "Defender" + ], "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" + "subcategory": "Pricing & Settings", + "text": "Data collection set to 'Common'" }, { - "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", - "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." + "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": [ + "Defender" + ], + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Defender for Cloud enhanced security features are all enabled" }, { - "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": "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": [ + "AzurePolicy", + "Defender" + ], "severity": "Medium", - "subcategory": "Governance", - "text": "Azure Storage encryption is enabled by default" + "subcategory": "Pricing & Settings", + "text": "Auto-provisioning enabled as per company policy (policy must exist)" }, { - "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", - "severity": "Medium", - "subcategory": "Governance", - "text": " " + "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": [ + "AzurePolicy", + "Defender" + ], + "severity": "Low", + "subcategory": "Pricing & Settings", + "text": "Email notifications enabled as per company policy (policy must exist)" }, { - "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", + "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": [ + "Defender" + ], "severity": "Medium", - "subcategory": "Governance", - "text": " " + "subcategory": "Pricing & Settings", + "text": "Enable integrations options are selected " }, { - "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", + "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": [ + "Defender" + ], "severity": "Medium", - "subcategory": " ", - "text": "Do not combine ASCS and Database cluster on to single/same VM" + "subcategory": "Pricing & Settings", + "text": "CI/CD integration is configured" }, { - "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", - "severity": "Medium", - "subcategory": " ", - "text": "Make sure the Floating IP is enabled on the Load balancer" + "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": [ + "EventHubs", + "Defender" + ], + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Continuous export 'Event Hub' is enabled if using 3rd party SIEM" }, { - "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/", + "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": [ + "Defender", + "Monitor", + "Sentinel" + ], "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" + "subcategory": "Pricing & Settings", + "text": "Continuous export 'Log Analytics Workspace' is enabled if not using Azure Sentinel" }, { - "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/", - "severity": "Medium", - "subcategory": " ", - "text": "Use one proximity placement group per SAP SID. Groups don't span across Availability Zones or Azure regions" + "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": [ + "Defender" + ], + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Cloud connector enabled for AWS" }, { - "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", - "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." + "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": [ + "Defender" + ], + "severity": "High", + "subcategory": "Pricing & Settings", + "text": "Cloud connector enabled for GCP" }, { - "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", - "severity": "Medium", - "subcategory": " ", - "text": "Use a Standard Load Balancer SKU in front of ASCS and DB clusters" - }, - { - "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", - "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": "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", - "severity": "Medium", - "subcategory": " ", - "text": "Native database replication technology should be used to synchronize the database in a HA pair." - }, - { - "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", - "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": "Business Continuity and Disaster Recovery", - "checklist": "Azure Landing Zone Review", - "guid": "81b12318-1a54-4174-8583-3fb4ae3c2df7", - "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": "Business Continuity and Disaster Recovery", - "checklist": "Azure Landing Zone Review", - "guid": "43165c3a-cbe0-45bb-b209-d490da477784", - "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)." - }, - { - "category": "Business Continuity and Disaster Recovery", - "checklist": "Azure Landing Zone Review", - "guid": "24d11678-5d2f-4a56-a56a-d48408fe7273", - "severity": "Medium", - "subcategory": " ", - "text": "Native database replication should be used to synchronize data to the DR site, rather than Azure Site Recovery" - }, - { - "category": "Storage", - "checklist": "Azure Landing Zone Review", - "guid": "d579266b-cca2-475f-aa1a-bfe9d55d04c3", - "severity": "Medium", - "subcategory": " ", - "text": "Disk config for Oracle, SQL, HANA" - }, - { - "category": "Compute", - "checklist": "Azure Landing Zone Review", - "guid": "2829e2ed-b217-4367-9aff-6691b4935ada", - "severity": "Medium", - "subcategory": " ", - "text": "Make quota requests for correct VM SKU and Zones" - }, - { - "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", - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Security Center/Defender enable in all subscriptions" - }, - { - "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", - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Security Center/Defender enabled on all Log Analytics workspaces" - }, - { - "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", - "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Data collection set to 'Common'" - }, - { - "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", - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Defender for Cloud enhanced security features are all enabled" - }, - { - "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", - "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Auto-provisioning enabled as per company policy (policy must exist)" - }, - { - "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", - "severity": "Low", - "subcategory": "Pricing & Settings", - "text": "Email notifications enabled as per company policy (policy must exist)" - }, - { - "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", - "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Enable integrations options are selected " - }, - { - "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", - "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "CI/CD integration is configured" - }, - { - "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", - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Continuous export 'Event Hub' is enabled if using 3rd party SIEM" - }, - { - "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", - "severity": "Medium", - "subcategory": "Pricing & Settings", - "text": "Continuous export 'Log Analytics Workspace' is enabled if not using Azure Sentinel" - }, - { - "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", - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Cloud connector enabled for AWS" - }, - { - "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", - "severity": "High", - "subcategory": "Pricing & Settings", - "text": "Cloud connector enabled for GCP" - }, - { - "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", - "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." + "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", + "Monitor" + ], + "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." }, { "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": [ + "Defender" + ], "severity": "Medium", "subcategory": "Recommendations", "text": "All recommendations remediated or disabled if not required." @@ -7406,6 +11455,9 @@ "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": [ + "Defender" + ], "severity": "High", "subcategory": "Recommendations", "text": "Security Score>70%" @@ -7415,6 +11467,10 @@ "checklist": "Azure Security Review Checklist", "guid": "50259226-4429-42bb-9285-37a55119bf8e", "link": "https://learn.microsoft.com/azure/defender-for-cloud/tutorial-security-incident", + "services": [ + "Monitor", + "Defender" + ], "severity": "Medium", "subcategory": "Security Alerts", "text": "Security Alerts contain only those generated in the past 24 hours (remediate or disable older security alerts)" @@ -7424,6 +11480,9 @@ "checklist": "Azure Security Review Checklist", "guid": "8f585428-7d9c-4dc1-96cd-072af9b141a8", "link": "https://learn.microsoft.com/azure/security-center/custom-dashboards-azure-workbooks", + "services": [ + "Defender" + ], "severity": "Medium", "subcategory": "Workbooks", "text": "If continuous export is enabled, default workbooks published to custom security dashboard" @@ -7433,6 +11492,9 @@ "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": [ + "Defender" + ], "severity": "Medium", "subcategory": "Community", "text": "Customer is aware of the value of the 'Community' page and has a regular cadence set up to review" @@ -7443,6 +11505,10 @@ "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": [ + "Subscriptions", + "Defender" + ], "severity": "High", "subcategory": "Secure Score", "text": "All subscriptions protected by Security Center are shown (no subscription filter set)" @@ -7452,6 +11518,9 @@ "checklist": "Azure Security Review Checklist", "guid": "bdddea8a-487c-4deb-9861-bc3bc14aea6e", "link": "https://learn.microsoft.com/azure/security-center/security-center-compliance-dashboard", + "services": [ + "Defender" + ], "severity": "High", "subcategory": "Regulatory Compliance", "text": "Compliance controls are green for any required compliance requirements" @@ -7462,6 +11531,10 @@ "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": [ + "Defender", + "VM" + ], "severity": "High", "subcategory": "Azure Defender", "text": "High severity VM vulnerabilities is zero (empty)" @@ -7471,6 +11544,10 @@ "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": [ + "Defender", + "Firewall" + ], "severity": "Medium", "subcategory": "Firewall Manager", "text": "Hubs are protected by an Azure Firewall" @@ -7481,6 +11558,11 @@ "description": "Customer Operational best practice - verify", "guid": "b47a393a-0803-4272-a479-8b1578a219a4", "link": "https://learn.microsoft.com/azure/security/fundamentals/network-best-practices", + "services": [ + "VNet", + "Defender", + "Firewall" + ], "severity": "Medium", "subcategory": "Firewall Manager", "text": "Virtual Networks are protected by a Firewall" @@ -7490,6 +11572,11 @@ "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": [ + "Defender", + "DDoS", + "Firewall" + ], "severity": "Medium", "subcategory": "Firewall Manager", "text": "DDoS Standard enabled" @@ -7499,6 +11586,10 @@ "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": [ + "Subscriptions", + "Defender" + ], "severity": "High", "subcategory": "Coverage", "text": "Verify that all subscriptions are covered (see pricing and settings to modify)" @@ -7508,6 +11599,10 @@ "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": [ + "VNet", + "VM" + ], "severity": "High", "subcategory": "Public IPs", "text": "VM's with public IPs should be protected by NSG " @@ -7518,6 +11613,11 @@ "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": [ + "EventHubs", + "Firewall", + "VM" + ], "severity": "High", "subcategory": "Public IPs", "text": "VMs with public IPs are moved behind Azure Firewall Premium" @@ -7528,6 +11628,9 @@ "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)" @@ -7537,6 +11640,10 @@ "checklist": "Azure Security Review Checklist", "guid": "158e3ea3-a93c-42de-9e31-65c3a87a04b7", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview", + "services": [ + "VNet", + "RBAC" + ], "severity": "Medium", "subcategory": "NSG", "text": "NSG RBAC is used to restrict access to network security team" @@ -7547,6 +11654,9 @@ "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": [ + "VNet" + ], "severity": "High", "subcategory": "NSG", "text": "NSG Inbound security rules do not contain a * (wildcard) in Source field" @@ -7557,6 +11667,9 @@ "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": [ + "VNet" + ], "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" @@ -7567,6 +11680,9 @@ "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": [ + "VNet" + ], "severity": "High", "subcategory": "NSG", "text": "NSG do not have Source as a * (wildcard) in place." @@ -7576,6 +11692,10 @@ "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": [ + "VNet", + "Sentinel" + ], "severity": "Medium", "subcategory": "NSG", "text": "NSG Diagnostics send NetworkSecurityGroupEvent and NetworkSecurityGroupRuleCounter traffic to Sentinel LAW" @@ -7585,6 +11705,10 @@ "checklist": "Azure Security Review Checklist", "guid": "aa124b6e-4df5-485e-adce-9793b7bcdb3b", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", + "services": [ + "VNet", + "RBAC" + ], "severity": "Medium", "subcategory": "UDR", "text": "UDR RBAC is used to restrict access to the network security team" @@ -7594,6 +11718,10 @@ "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", + "Firewall" + ], "severity": "High", "subcategory": "UDR", "text": "If Zero Trust, then UDR's are used to send all traffic to the Azure Firewall Premium" @@ -7604,6 +11732,9 @@ "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": [ + "VNet" + ], "severity": "Medium", "subcategory": "UDR", "text": "UDR's that do not send all traffic to AzureFirewallPremium are known and documented." @@ -7613,6 +11744,9 @@ "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": [ + "VNet" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "Customer is familiar with Azure networking defaults / SDN default routing in Azure" @@ -7623,6 +11757,10 @@ "description": "Customer operational best practice - verify", "guid": "a87a04b7-a209-4939-ada4-7778f24c1167", "link": "https://github.com/MicrosoftDocs/azure-docs/issues/53672", + "services": [ + "VNet", + "RBAC" + ], "severity": "Medium", "subcategory": "Virtual Networks", "text": "VNet RBAC is used to restrict access to the network security team" @@ -7632,6 +11770,9 @@ "checklist": "Azure Security Review Checklist", "guid": "85c2fa55-b56a-4948-808b-e7d7e4c476b6", "link": "https://learn.microsoft.com/azure/virtual-network/policy-reference", + "services": [ + "VNet" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet Security recommendations are remediated and there are no 'At-risk' VNets " @@ -7641,6 +11782,9 @@ "checklist": "Azure Security Review Checklist", "guid": "d8bdcf59-bce6-45de-aa13-f98879468d66", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-peering-overview", + "services": [ + "VNet" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet Peering connections are understood and expected traffic flows are documented" @@ -7650,6 +11794,9 @@ "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": [ + "VNet" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet Service Endpoints are in use, no legacy Public Service Endpoints exist" @@ -7659,6 +11806,10 @@ "checklist": "Azure Security Review Checklist", "guid": "1f625659-ee55-480a-9824-9c931213dbd7", "link": "https://learn.microsoft.com/azure/private-link/private-endpoint-overview", + "services": [ + "VNet", + "PrivateLink" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet Private Endpoints are in use to allow access from on-premises environments, no legacy public endpoints exist" @@ -7668,6 +11819,10 @@ "checklist": "Azure Security Review Checklist", "guid": "fb012f70-943f-4630-9722-ea39d2b1ce63", "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", + "services": [ + "VNet", + "Monitor" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet Monitoring enabled" @@ -7677,6 +11832,11 @@ "checklist": "Azure Security Review Checklist", "guid": "2055b29b-ade4-4aad-8e8c-39ec94666731", "link": "https://learn.microsoft.com/azure/virtual-network/kubernetes-network-policies", + "services": [ + "AzurePolicy", + "VNet", + "AKS" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "Secure traffic between pods using network policies in Azure Kubernetes Service (AKS)" @@ -7686,6 +11846,10 @@ "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": [ + "VNet", + "NVA" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet NVA (appliances) customer follows published architecture pattern" @@ -7695,6 +11859,11 @@ "checklist": "Azure Security Review Checklist", "guid": "b375a917-ecbe-448f-ae64-dd7df2e8bbbc", "link": "https://learn.microsoft.com/azure/virtual-network/monitor-virtual-network", + "services": [ + "VNet", + "Monitor", + "Sentinel" + ], "severity": "High", "subcategory": "Virtual Networks", "text": "VNet Diagnostic settings are enabled and sending VMProtectionAlerts to the Azure Sentinel LAW" @@ -7704,6 +11873,10 @@ "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": [ + "VPN", + "ExpressRoute" + ], "severity": "High", "subcategory": "Connectivity", "text": "Use ExpressRoute or VPN to access Azure resources from on-premises environments" @@ -7713,6 +11886,10 @@ "checklist": "Azure Security Review Checklist", "guid": "bd8ac2aa-ebca-42a4-9da1-dbf3dd992481", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", + "services": [ + "VWAN", + "RBAC" + ], "severity": "High", "subcategory": "Virtual WAN", "text": "VWAN RBAC is used to restrict access to the network security team" @@ -7722,6 +11899,10 @@ "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": [ + "Monitor", + "VWAN" + ], "severity": "High", "subcategory": "Virtual WAN", "text": "VWAN Customer is using Secure Hub or external Firewall to route and monitor traffic." @@ -7731,6 +11912,10 @@ "checklist": "Azure Security Review Checklist", "guid": "1213dbd7-fb01-42f7-8943-f6304722ea39", "link": "https://learn.microsoft.com/azure/web-application-firewall/overview", + "services": [ + "AppGW", + "RBAC" + ], "severity": "High", "subcategory": "Application Gateway", "text": "AppGW RBAC is used to restrict access to the network security team" @@ -7740,6 +11925,11 @@ "checklist": "Azure Security Review Checklist", "guid": "d2b1ce63-2055-4b29-aade-4aad1e8c39ec", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-front-end-ip", + "services": [ + "AppGW", + "EventHubs", + "WAF" + ], "severity": "High", "subcategory": "Application Gateway", "text": "AppGW All external facing web services are behind Application Gateways with WAF enabled " @@ -7749,6 +11939,11 @@ "checklist": "Azure Security Review Checklist", "guid": "94666731-3c00-4567-9c1e-945b459c373e", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-front-end-ip", + "services": [ + "AppGW", + "EventHubs", + "WAF" + ], "severity": "High", "subcategory": "Application Gateway", "text": "AppGW All internal facing web services are behind Application Gateways with WAF enabled " @@ -7758,6 +11953,9 @@ "checklist": "Azure Security Review Checklist", "guid": "7ed71623-b375-4a91-9ecb-e48fbe64dd7d", "link": "https://learn.microsoft.com/azure/application-gateway/ssl-overview", + "services": [ + "AppGW" + ], "severity": "High", "subcategory": "Application Gateway", "text": "AppGW - External facing has TLS/SSL enabled and redirects all traffic to 443 (no port 80 traffic)" @@ -7767,6 +11965,10 @@ "checklist": "Azure Security Review Checklist", "guid": "f2e8bbbc-4681-455a-ac91-64e9909aed8c", "link": "https://learn.microsoft.com/azure/frontdoor/", + "services": [ + "FrontDoor", + "RBAC" + ], "severity": "High", "subcategory": "FrontDoor", "text": "Front Door RBAC is used to restrict access to the network security team" @@ -7776,6 +11978,11 @@ "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": [ + "AzurePolicy", + "FrontDoor", + "WAF" + ], "severity": "High", "subcategory": "FrontDoor", "text": "Front Door is associated with a WAF policy" @@ -7785,6 +11992,10 @@ "checklist": "Azure Security Review Checklist", "guid": "ce574dcc-bd8a-4c2a-aebc-a2a44da1dbf3", "link": "https://learn.microsoft.com/azure/frontdoor/front-door-custom-domain-https", + "services": [ + "AzurePolicy", + "FrontDoor" + ], "severity": "High", "subcategory": "FrontDoor", "text": "Front Door TLS/SSL policy is configured" @@ -7794,6 +12005,9 @@ "checklist": "Azure Security Review Checklist", "guid": "dd992481-718d-41dc-a1f6-25659ee5580a", "link": "https://learn.microsoft.com/azure/frontdoor/front-door-url-redirect", + "services": [ + "FrontDoor" + ], "severity": "High", "subcategory": "FrontDoor", "text": "Front Door redirect port 80 to port 443 is configured (listeners)" @@ -7803,6 +12017,10 @@ "checklist": "Azure Security Review Checklist", "guid": "38249c93-1213-4dbd-9fb0-12f70943f630", "link": "https://learn.microsoft.com/azure/frontdoor/front-door-diagnostics", + "services": [ + "FrontDoor", + "Sentinel" + ], "severity": "High", "subcategory": "FrontDoor", "text": "Front Door diagnostics logs send ApplicationGatewayAccessLog &ApplicationGateway FirewallLog to Sentinel LAW" @@ -7812,6 +12030,9 @@ "checklist": "Azure Security Review Checklist", "guid": "4722ea39-d2b1-4ce6-9205-5b29bade4aad", "link": "https://learn.microsoft.com/azure/security/fundamentals/ddos-best-practices", + "services": [ + "DDoS" + ], "severity": "High", "subcategory": "DDOS Protection", "text": "Enabled for Firewall public IP's (all public IPs)" @@ -7821,6 +12042,9 @@ "checklist": "Azure Security Review Checklist", "guid": "346ad56f-bdb8-44db-8bcd-0a689af63f1e", "link": "https://learn.microsoft.com/security/compass/identity#a-single-enterprise-directory", + "services": [ + "Entra" + ], "severity": "High", "subcategory": "Tenant", "text": "Establish a single enterprise directory for managing identities of full-time employees and enterprise resources." @@ -7830,6 +12054,9 @@ "checklist": "Azure Security Review Checklist", "guid": "a46108cd-6a76-4749-ae69-b7bf61410010", "link": "https://learn.microsoft.com/security/compass/identity#synchronized-identity-systems", + "services": [ + "Entra" + ], "severity": "High", "subcategory": "Tenant", "text": "Synchronize your cloud identity with your existing identity systems." @@ -7839,6 +12066,9 @@ "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": [ + "Entra" + ], "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." @@ -7848,6 +12078,9 @@ "checklist": "Azure Security Review Checklist", "guid": "343473ec-ed5c-49e1-98f4-cb09524a23cd", "link": "https://learn.microsoft.com/security/compass/identity#block-legacy-authentication", + "services": [ + "Entra" + ], "severity": "High", "subcategory": "Tenant", "text": "Disable insecure legacy protocols for internet-facing services." @@ -7857,6 +12090,9 @@ "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": [ + "Entra" + ], "severity": "High", "subcategory": "Tenant", "text": "Enable single sign-on" @@ -7866,6 +12102,9 @@ "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": [ + "Entra" + ], "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." @@ -7875,6 +12114,9 @@ "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": [ + "Entra" + ], "severity": "High", "subcategory": "Privileged administration", "text": "Limit the number of Global Administrators to less than 5" @@ -7884,6 +12126,10 @@ "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": [ + "RBAC", + "Entra" + ], "severity": "High", "subcategory": "Privileged administration", "text": "Use groups for Azure AD role assignments and delegate the role assignment" @@ -7893,6 +12139,10 @@ "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": [ + "AzurePolicy", + "Entra" + ], "severity": "High", "subcategory": "Privileged administration", "text": "Ensure all critical impact admins are managed by enterprise directory to follow organizational policy enforcement." @@ -7902,1297 +12152,9593 @@ "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": [ + "Entra" + ], "severity": "High", "subcategory": "Privileged administration", "text": "Configure recurring access reviews to revoke unneeded permissions over time" }, { - "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": "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": [ + "Monitor", + "Entra" + ], + "severity": "Medium", + "subcategory": "Privileged administration", + "text": "Ensure critical impact admins use a workstation with elevated security protections and monitoring" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "External Identities", + "text": "Identity Providers: Verify external identity providers are known" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "External Identities", + "text": "External Collaboration Settings: Guest user access set to 'Guest user access is restricted?'" + }, + { + "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": [ + "RBAC", + "Entra" + ], + "severity": "High", + "subcategory": "External Identities", + "text": "External Collaboration Settings: Guest invite settings set to 'Only users assigned to specific admin roles'" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "External Identities", + "text": "External Collaboration Settings: Enable guest self-service sign up via flows set to 'Disabled' " + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "External Identities", + "text": "External Collaboration Settings: Collaboration restrictions set to 'Allow invitations to the specified domains'" + }, + { + "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": [ + "Entra" + ], + "severity": "Medium", + "subcategory": "External Identities", + "text": "Access Reviews: Enabled for all groups" + }, + { + "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": [ + "Entra" + ], + "severity": "Medium", + "subcategory": "Enterprise Applications", + "text": "Consent & Permissions: Allow user consent for apps from verified publishers" + }, + { + "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": "Enterprise Applications", + "text": "Consent & Permissions: Allow group owner consent for selected group owners " + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "Custom Domains", + "text": "Only validated customer domains are registered" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "High", + "subcategory": "Password Reset", + "text": "Self-service password reset policy requirement verified compliant." + }, + { + "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": [ + "Entra" + ], + "severity": "Medium", + "subcategory": "Password Reset", + "text": "Set number of days before users are asked to re-confirm authentication information is not set to zero" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "Password Reset", + "text": "Set number of methods required to reset password are selected" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "User Setting", + "text": "Disable 'Users can register applications'" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "User Setting", + "text": "Restrict access to Administrative portal (portal.azure.com) to administrators only" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "User Setting", + "text": "Disable 'LinkedIn account connection'" + }, + { + "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": [ + "Entra", + "Monitor", + "Sentinel" + ], + "severity": "High", + "subcategory": "Diagnostic Settings", + "text": "Enabled and send to Log Analytics workspace with Sentinel" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "PIM enabled", + "text": "Privileged Identity Management enabled" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "PIM enabled", + "text": "Implement 'just in time' (JIT) access to further lower the exposure time for privileged accounts (reduce standing access)" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Configure conditional access policies / Access Controls" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "Medium", + "subcategory": "Conditional Access Policies", + "text": "Conditions: Restricted Locations" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: MFA enabled for all users" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "Medium", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Require MFA for Administrators" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Require MFA for Azure Management " + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Block Legacy Protocols" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "High", + "subcategory": "Conditional Access Policies", + "text": "Access Controls: Require devices to be marked as compliant" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "Medium", + "subcategory": "Guest users", + "text": "Is there a policy to track guest user accounts (i.e. usage/delete/disable)?" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "Identity Secure Score", + "text": "Implement Identity Secure Score based on best practices in your industry" + }, + { + "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": [ + "AzurePolicy", + "Entra" + ], + "severity": "Medium", + "subcategory": "Break Glass Accounts", + "text": "At least two break glass accounts have been created and policy around their use exists" + }, + { + "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": [ + "AzurePolicy", + "VM" + ], + "severity": "High", + "subcategory": "Access Control", + "text": "Control VM Access leveraging Azure Policy" + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "Access Control", + "text": "Reduce variability in your setup and deployment of VMs by leveraging templates" + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "Access Control", + "text": "Secure privileged access to deploy VMS by reducing who has access to Resources through Governance" + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Use multiple VMs for your workloads for better availability " + }, + { + "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": [ + "ASR", + "VM" + ], + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Deploy and test a disaster recovery solution " + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Availability sets" + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Availability Zones" + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "High Availability ", + "text": "Regional fault tolerance " + }, + { + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Protect against malware", + "text": "Install antimalware solutions" + }, + { + "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": [ + "Defender", + "VM" + ], + "severity": "High", + "subcategory": "Protect against malware", + "text": "Integrate antimalware solution with Security Center" + }, + { + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Manage VM Updates", + "text": "Keep VMs up to date using Update Management with Azure Automation" + }, + { + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "Manage VM Updates", + "text": "Ensure Windows images for deployment have the most recent level of updates " + }, + { + "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": [ + "Defender", + "VM" + ], + "severity": "High", + "subcategory": "Manage VM Updates", + "text": "Rapidly apply security updates to VMs using Microsoft Defender for Cloud" + }, + { + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Encrypt your VHDs", + "text": "Enable encryption on your VMs" + }, + { + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Encrypt your VHDs", + "text": "Add Key Encryption Key (KEK) for added layer of security for encryption " + }, + { + "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": [ + "VM", + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": "Encrypt your VHDs", + "text": "Take a snapshot of disks before encryption for rollback purposes" + }, + { + "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": [ + "Entra", + "VM" + ], + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Ensure only the central networking group has permissions to networking resources " + }, + { + "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": [ + "Entra", + "VM" + ], + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Identity and remediate exposed VMs that allow access from 'ANY' source IP address" + }, + { + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Restrict management ports (RDP, SSH) using Just-in-Time Access" + }, + { + "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": [ + "VM" + ], + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Remove internet access and implement jump servers for RDP" + }, + { + "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": [ + "VPN", + "VM" + ], + "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": "VM Security Checks", + "checklist": "Azure Security Review Checklist", + "guid": "dad6aae1-1e6b-484e-b5df-47d2d92881b1", + "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", + "services": [ + "VM", + "Bastion" + ], + "severity": "High", + "subcategory": "Restrict direct internet connection ", + "text": "Leverage Azure Bastion as your RDP/SSH broker for added security and reduction in footprint" + }, + { + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "cd5d1e54-a297-459e-9968-0e78289c9356", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", + "services": [ + "Monitor", + "Sentinel" + ], + "severity": "High", + "subcategory": "Architecture ", + "text": "All tenants contain have Sentinel enabled on at least one Log Analytics workspace" + }, + { + "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": [ + "Sentinel" + ], + "severity": "High", + "subcategory": "Architecture ", + "text": "Customer understands Sentinel architecture" + }, + { + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "e8f5c586-c7d9-4cdc-86ac-c075ef9b141a", + "link": "https://learn.microsoft.com/azure/sentinel/multiple-workspace-view", + "services": [ + "ACR", + "Monitor", + "Sentinel" + ], + "severity": "Medium", + "subcategory": "Architecture ", + "text": "Customer knows how to monitor Incidents across multiple Sentinel instances" + }, + { + "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": [ + "Sentinel" + ], + "severity": "Medium", + "subcategory": "Overview", + "text": "No Incidents open more than 24 hours" + }, + { + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "5d3c4ada-97cb-43d1-925a-b225c6f4e068", + "link": "https://learn.microsoft.com/azure/sentinel/whats-new", + "services": [ + "Sentinel" + ], + "severity": "Low", + "subcategory": "News & Guides", + "text": "Customer have been shown the News & Guides tab" + }, + { + "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": [ + "Sentinel" + ], + "severity": "Medium", + "subcategory": "UEBA ", + "text": "UEBA Configured (Sentinel/Settings/Settings/Configure UEBA)" + }, + { + "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": [ + "Sentinel", + "Entra" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Azure Active Directory in configured and 'Last Log Received' shows today" + }, + { + "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": [ + "Sentinel", + "Entra" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Azure Active Directory Identity Protection is configured and 'Last Log Received' shows today" + }, + { + "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": [ + "Sentinel" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Azure Activity is configured is configured and 'Last Log Received' shows today" + }, + { + "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": [ + "Defender", + "Sentinel" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Microsoft Defender for Cloud is configured and 'Last Log Received' shows today" + }, + { + "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": [ + "Sentinel", + "Firewall" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Azure Firewall is configured and 'Last Log Received' shows today" + }, + { + "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": [ + "Sentinel" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Windows Firewall is configured and 'Last Log Received' shows today" + }, + { + "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": [ + "Sentinel" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Security Events is configured with AMA and 'Last Log Received' shows today" + }, + { + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "1a4834ac-9322-423e-ae80-b123081a5417", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", + "services": [ + "Sentinel" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Security Events - verify Azure computers are connected and sending data to the workspace" + }, + { + "category": "Sentinel", + "checklist": "Azure Security Review Checklist", + "guid": "859c773e-7e26-4162-9b77-5a917e1f348e", + "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", + "services": [ + "Sentinel" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Security Events - verify non-Azure computers are connected and sending data to the workspace" + }, + { + "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" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Connector for AWS" + }, + { + "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" + ], + "severity": "High", + "subcategory": "Data Connectors", + "text": "Connector for GCP" + }, + { + "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": "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" + ], + "severity": "Medium", + "subcategory": "Settings", + "text": "Customer does not have a daily cap enabled" + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "9e3558fd-7724-49c9-9111-2d027fe412f7", + "link": "https://learn.microsoft.com/azure/firewall/premium-features", + "services": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Configuration", + "text": "Azure Firewall Premium deployed" + }, + { + "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" + ], + "severity": "High", + "subcategory": "Configuration", + "text": "Quad zero/force tunning enabled through Azure Firewall" + }, + { + "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": [ + "RBAC", + "Firewall" + ], + "severity": "Medium", + "subcategory": "Access Control", + "text": "RBAC set to enable only authorized users" + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "8093dc9f-c9d1-4bb7-9b36-a5a67fbb9ed5", + "link": "https://learn.microsoft.com/azure/firewall/firewall-diagnostics", + "services": [ + "Monitor", + "Firewall" + ], + "severity": "Medium", + "subcategory": "Diagnostic Settings", + "text": "Diagnostics enabled and sending metrics to a Log Analytics workspace " + }, + { + "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" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Hubs and virtual networks are protected or connected through Firewall Premium" + }, + { + "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": [ + "AzurePolicy", + "RBAC", + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Access controls are configured (RBAC)" + }, + { + "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": [ + "AzurePolicy", + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Parent policy is configured " + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "15675c1e-a55b-446a-a48f-f8ae7d7e4b47", + "link": "https://learn.microsoft.com/azure/firewall/rule-processing", + "services": [ + "AzurePolicy", + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Rule collections are defined" + }, + { + "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", + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: DNAT policies are defined" + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "d66a786d-60e9-46c9-9ad8-855d04c2b39c", + "link": "https://learn.microsoft.com/azure/firewall/rule-processing", + "services": [ + "AzurePolicy", + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Network rules are defined" + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "986bb2c1-2149-4a11-9b5e-3df574ecccd9", + "link": "https://learn.microsoft.com/azure/firewall/features", + "services": [ + "AzurePolicy", + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Policy: Application rules are defined" + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "793a6bcd-a3b5-40eb-8eb0-3dd95d58d7c8", + "link": "https://learn.microsoft.com/azure/firewall/dns-details", + "services": [ + "Firewall", + "DNS" + ], + "severity": "Medium", + "subcategory": "Firewall Manager", + "text": "DNS: Feature understood and applied or not applied" + }, + { + "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" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Threat Intelligence: Set to Alert & Deny" + }, + { + "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": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "Threat Intelligence: Allowed list (justify if they are being used - ie performance)" + }, + { + "category": "Azure Firewall", + "checklist": "Azure Security Review Checklist", + "guid": "623b365a-917e-4cbe-98eb-d54cd7df2e8b", + "link": "https://learn.microsoft.com/azure/firewall/premium-certificates", + "services": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "TLS enabled" + }, + { + "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" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "IDPS enabled" + }, + { + "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" + ], + "severity": "High", + "subcategory": "Firewall Manager", + "text": "SNAT: Configured " + }, + { + "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": [ + "DDoS", + "Firewall" + ], + "severity": "Medium", + "subcategory": "DDOS Protection", + "text": "Enabled for Firewall public IP's" + }, + { + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "41177955-fe8f-430b-ae72-20dc5b6880da", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/overview", + "services": [ + "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." + }, + { + "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": "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": "Business", + "text": "Define your pricing model and ensure it aligns with your tenants' consumption of Azure resources." + }, + { + "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": "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": "Business", + "text": "Based on your customers' requirements, decide on the tenancy models that are appropriate for various parts of your solution." + }, + { + "category": "Business", + "checklist": "Multitenant architecture", + "guid": "f5d76ae1-7048-4ff5-abba-f1ca799578b9", + "link": "https://learn.microsoft.com/azure/marketplace/plan-saas-offer", + "services": [ + "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": "Reliability", + "text": "Review the Azure Well-Architected Reliability checklist, which is applicable to all workloads." + }, + { + "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": "Reliability", + "text": "Understand the Noisy Neighbor antipattern. Prevent individual tenants from impacting the system's availability for other tenants." + }, + { + "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": "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": "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": "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": "Security", + "text": "Apply the Zero Trust and least privilege principles in all layers of your solution." + }, + { + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "92160e00-6894-4102-97e0-615d4ed93c01", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/map-requests", + "services": [ + "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." + }, + { + "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": "Security", + "text": "Understand your tenants' compliance requirements, including data residency and any compliance or regulatory standards that they require you to meet." + }, + { + "category": "Security", + "checklist": "Multitenant architecture", + "guid": "30adb90d-83d4-4a2e-986e-327ffe04e7a5", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/considerations/domain-names", + "services": [ + "DNS" + ], + "severity": "High", + "subcategory": "Security", + "text": "Correctly manage domain names and avoid vulnerabilities like dangling DNS and subdomain takeover attacks." + }, + { + "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": [ + "Cost" + ], + "severity": "Medium", + "subcategory": "Cost Optimization", + "text": "Review the Azure Well-Architected Operational Excellence checklist, which is applicable to all workloads." + }, + { + "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": [ + "Cost" + ], + "severity": "High", + "subcategory": "Cost Optimization", + "text": "Ensure you can adequately measure per-tenant consumption and correlate it with your infrastructure costs." + }, + { + "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": [ + "Cost", + "Monitor" + ], + "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." + }, + { + "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": "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." + }, + { + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "a3f80518-d428-4c02-b2cc-dfaef47db7e2", + "services": [ + "Monitor" + ], + "severity": "High", + "subcategory": "Operational Excellence", + "text": "Monitor the health of the overall system, as well as each tenant." + }, + { + "category": "Operational Excellence", + "checklist": "Multitenant architecture", + "guid": "dfb42da5-f871-4953-9e5c-da6fda3f1411", + "services": [ + "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": "Operational Excellence", + "text": "Organize your Azure resources for isolation and scale." + }, + { + "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": "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." + }, + { + "category": "Performance Efficiency", + "checklist": "Multitenant architecture", + "guid": "6acf7eb5-24a3-47c7-ae87-1196cd96048e", + "link": "https://learn.microsoft.com/azure/architecture/guide/multitenant/approaches/compute", + "services": [ + "Storage" + ], + "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." + }, + { + "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": "BCDR", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Ensure that your backups are protected against attacks. This should include encryption of the backups to protect against loss of confidentiality. For regular Azure service backup, backup data is automatically encrypted using Azure platform-managed keys. You can also choose to encrypt the backup using a customer-managed key. In this case, ensure this customer-managed key in the key vault is also in the backup scope.", + "guid": "676f6951-0368-49e9-808d-c33a692c9a64", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-2-encrypt-backup-data", + "services": [ + "SQL", + "Backup", + "AKV" + ], + "severity": "Medium", + "subcategory": "Azure Key Vault", + "text": "Protect your backup data with encryption and store keys safely in Azure Key Vault" + }, + { + "category": "BCDR", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Azure SQL Database uses SQL Server technology to create full backups every week, differential backup every 12-24 hours, and transaction log backup every 5 to 10 minutes. By default, SQL Database stores data in geo-redundant storage blobs that are replicated to a paired region.", + "guid": "e2518261-b3bc-4bd1-b331-637fb2df833f", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-1-ensure-regular-automated-backups", + "services": [ + "SQL", + "Backup", + "Storage" + ], + "severity": "Medium", + "subcategory": "Backup", + "text": "Configure Azure SQL Database automated backups" + }, + { + "category": "BCDR", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "By default, SQL Database stores data in geo-redundant storage blobs that are replicated to a paired region. For SQL Database, the backup storage redundancy can be configured at the time of database creation or can be updated for an existing database; the changes made to an existing database apply to future backups only.", + "guid": "f8c7cda2-3ed7-43fb-a100-85dcd12a0ee4", + "link": "https://learn.microsoft.com/azure/azure-sql/database/automated-backups-overview?tabs=single-database&view=azuresql#backup-storage-redundancy", + "services": [ + "SQL", + "Backup", + "Storage" + ], + "severity": "Low", + "subcategory": "Backup", + "text": "Enable geo-redundant backup storage to protect against single region failure and data loss" + }, + { + "category": "Code", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Malicious code can potentially circumvent security controls. Before deploying custom code to production, it is essential to review what's being deployed. Use a database tool like Azure Data Studio that supports source control. Implement tools and logic for code analysis, vulnerability and credential scanning.", + "guid": "7ca9f006-d2a9-4652-951c-de8e4ac5e76e", + "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-create-server", + "services": [ + "SQL" + ], + "severity": "Medium", + "subcategory": "Source Control and Code Review", + "text": "Use Source Control systems to store, maintain and review application code deployed inside Azure SQLDB Database" + }, + { + "category": "Data Discovery and Classification", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "In case of classification requirements Purview is the preferred option. Only use SQL Data Discovery & Classification in case Purview is not an option. Discover columns that potentially contain sensitive data. What is considered sensitive data heavily depends on the customer, compliance regulation, etc., and needs to be evaluated by the users in charge of that data. Classify the columns to use advanced sensitivity-based auditing and protection scenarios. Review results of automated discovery and finalize the classification if necessary.", + "guid": "d401509b-2629-4484-9a7f-af0d29a7778f", + "link": "https://learn.microsoft.com/azure/azure-sql/database/data-discovery-and-classification-overview?view=azuresql#faq---advanced-classification-capabilities", + "services": [ + "SQL" + ], + "severity": "Low", + "subcategory": "Data Discovery and Classification", + "text": "Plan and configure Data Discovery & Classification to protect the sensitive data" + }, + { + "category": "Data Masking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Usage of this feature is recommended only if column encryption is not an option and there is a specific requirement to preserve data types and formats. Dynamic data masking limits sensitive data exposure by masking it to non-privileged users. Dynamic data masking helps prevent unauthorized access to sensitive data by enabling customers to designate how much of the sensitive data to reveal with minimal impact on the application layer.", + "guid": "9391fd50-135e-453e-90a7-c1a23f88cc13", + "link": "https://learn.microsoft.com/azure/azure-sql/database/dynamic-data-masking-overview", + "services": [ + "SQL" + ], + "severity": "Low", + "subcategory": "Data Masking", + "text": "Use Data Masking to prevent unauthorized non-admin users data access if no encryption is possible" + }, + { + "category": "Defender", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "SQL Advanced Threat Detection (ATP) provides a layer of security that detects potential vulnerabilities and anomalous activity in databases such as SQL injection attacks and unusual behavior patterns. When a potential threat is detected Threat Detection sends an actionable real-time alert by email and in Microsoft Defender for Cloud, which includes clear investigation and remediation steps for the specific threat.", + "guid": "4e52d73f-5d37-428f-b3a2-e6997e835979", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-configure", + "services": [ + "SQL", + "EventHubs", + "Defender" + ], + "severity": "High", + "subcategory": "Advanced Threat Protection", + "text": "Review and complete Advanced Threat Protection (ATP) configuration" + }, + { + "category": "Defender", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Enable Microsoft Defender for Azure SQL at the subscription level to automatically onboard and protect all existing and future servers and databases. When you enable on the subscription level, all databases in Azure SQL Database and Azure SQL Managed Instance are protected. You can then disable them individually if you choose. If you want to manually manage which databases are protected, disable at the subscription level and enable each database that you want protected.", + "guid": "dff87489-9edb-4cef-bdda-86e8212b2aa1", + "link": "https://learn.microsoft.com/azure/azure-sql/database/azure-defender-for-sql?view=azuresql#enable-microsoft-defender-for-sql ", + "services": [ + "Subscriptions", + "SQL", + "Defender" + ], + "severity": "High", + "subcategory": "Defender for Azure SQL", + "text": "Enable Microsoft Defender for Azure SQL" + }, + { + "category": "Defender", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Microsoft Defender for Azure SQL ATP detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases. Alerts can be configured and generated and will be reported in the Defender for console.", + "guid": "ca342fdf-d25a-4427-b105-fcd50ff8a0ea", + "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-configure", + "services": [ + "Defender", + "SQL", + "Monitor" + ], + "severity": "High", + "subcategory": "Defender for Azure SQL", + "text": "Prepare a security response plan to promptly react to Microsoft Defender for Azure SQL alerts" + }, + { + "category": "Defender", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Azure SQLDB vulnerability assessment is a service that provides visibility into your security state. Vulnerability assessment includes actionable steps to resolve security issues and enhance your database security. It can help you to monitor a dynamic database environment where changes are difficult to track and improve your SQL security posture.", + "guid": "a6101ae7-534c-45ab-86fd-b34c55ea21ca", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/sql-azure-vulnerability-assessment-overview", + "services": [ + "SQL", + "Monitor", + "Defender" + ], + "severity": "High", + "subcategory": "Vulnerability Assessment", + "text": "Configure Vulnerability Assessment (VA) findings and review recommendations" + }, + { + "category": "Defender", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Microsoft Defender for Cloud provides vulnerability assessment for your Azure SQL Databases. Vulnerability assessment scans your databases for software vulnerabilities and provides a list of findings. You can use the findings to remediate software vulnerabilities and disable findings.", + "guid": "c8c5f112-1e50-4f77-9264-8195b4cd61ac", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/sql-azure-vulnerability-assessment-find?view=azuresql", + "services": [ + "SQL", + "Defender" + ], + "severity": "High", + "subcategory": "Vulnerability Assessment", + "text": "Regularly review of Vulnerability Assessment (VA) findings and recommendations and prepare a plan to fix" + }, + { + "category": "Encryption", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Always Encrypted with Secure Enclaves expands confidential computing capabilities of Always Encrypted by enabling in-place encryption and richer confidential queries. Always Encrypted with Secure Enclaves addresses these limitations by allowing some computations on plaintext data inside a secure enclave on the server side. Usage of this feature is recommended for the cases where you need to limit administrator access and need your queries to support more than equality matching of encrypted columns.", + "guid": "65d7e54a-10a6-4094-b673-9ff3809c9277", + "link": "https://learn.microsoft.com/sql/relational-databases/security/encryption/always-encrypted-enclaves", + "services": [ + "SQL" + ], + "severity": "Medium", + "subcategory": "Always Encrypted", + "text": "If protecting sensitive PII data from admin users is a key requirement, but Column Encryption limitations cannot be tolerated, consider the adoption of Always Encrypted with Secure Enclaves" + }, + { + "category": "Encryption", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "With Azure SQL Database, you can apply symmetric encryption to a column of data by using Transact-SQL. This approach is called column encryption, because you can use it to encrypt specific columns with different encryption keys. Doing so gives you more granular encryption capability than TDE, which encrypts data in pages. Using Always Encrypted to ensure sensitive data isn't exposed in plaintext in Azure SQL Database or SQL Managed Instance, even in memory/in use. Always Encrypted protects the data from Database Administrators (DBAs) and cloud admins (or bad actors who can impersonate high-privileged but unauthorized users) and gives you more control over who can access your data.", + "guid": "c03ce136-e3d5-4e17-bf25-ed955ee480d3", + "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" + ], + "severity": "Low", + "subcategory": "Column Encryption", + "text": "To protect sensitive PII data from non-admin users in specific table columns, consider using Column Encryption" + }, + { + "category": "Encryption", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Enabled by default, Transparent data encryption (TDE) helps to protect the database files against information disclosure by performing real-time encryption and decryption of the database, associated backups, and transaction log files 'at rest', without requiring changes to the application.", + "guid": "c614ac47-bebf-4061-b0a1-43e0c6b5e00d", + "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-create-server", + "services": [ + "SQL", + "Backup", + "Storage" + ], + "severity": "High", + "subcategory": "Transparent Data Encryption", + "text": "Ensure Transparent Data Encryption (TDE) is kept enabled" + }, + { + "category": "Encryption", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "If separation of duties in the management of keys and data within the organization is required, leverage Customer Managed Keys (CMK) for Transparent Data Encryption (TDE) for your Azure SQLDB and use Azure Key Vault to store (refer to its checklist). Leverage this feature when you have strict security requirements which cannot be met by the managed service keys.", + "guid": "2edb4165-4f54-47cc-a891-5c82c2f21e25", + "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-overview", + "services": [ + "SQL", + "AKV" + ], + "severity": "Medium", + "subcategory": "Transparent Data Encryption", + "text": "Use customer-managed keys (CMK) in Azure Key Vault (AKV) if you need increased transparency and granular control over the TDE protection" + }, + { + "category": "Encryption", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The minimal Transport Layer Security (TLS) version setting allows customers to choose which version of TLS their SQL database uses. It's possible to change the minimum TLS version by using the Azure portal, Azure PowerShell, and the Azure CLI.", + "guid": "7754b605-57fd-4bcb-8213-52c39d8e8225", + "link": "https://learn.microsoft.com/azure/azure-sql/database/connectivity-settings?source=recommendations&view=azuresql&tabs=azure-portal#minimal-tls-version", + "services": [ + "SQL" + ], + "severity": "High", + "subcategory": "Transport Layer Security", + "text": "Enforce minimum TLS version to the latest available" + }, + { + "category": "Identity", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Use Azure Active Directory (Azure AD) authentication for centralized identity management. Use SQL Authentication only if really necessary and document as exceptions.", + "guid": "c9b8b6bf-2c6b-453d-b400-de9a43a549d7", + "link": "https://learn.microsoft.com/azure/azure-sql/database/authentication-aad-overview", + "services": [ + "SQL", + "Entra" + ], + "severity": "Medium", + "subcategory": "Azure Active Directory", + "text": "Leverage Azure AD authentication for connections to Azure SQL Databases" + }, + { + "category": "Identity", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Using Azure AD groups simplifies permission management and both the group owner, and the resource owner can add/remove members to/from the group. Create a separate group for Azure AD administrators for each logical server. Monitor Azure AD group membership changes using Azure AD audit activity reports.", + "guid": "29820254-1d14-4778-ae90-ff4aeba504a3", + "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#central-management-for-identities", + "services": [ + "SQL", + "Monitor", + "Entra" + ], + "severity": "Medium", + "subcategory": "Azure Active Directory", + "text": "Create a separate Azure AD group with two admin accounts for each Azure SQL Database logical server" + }, + { + "category": "Identity", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Ensure that distinct system and user assigned managed identities, that are dedicated to the function, with least permissions assigned, are used for communication from Azure services and applications to the Azure SQLDB databases.", + "guid": "df3a09ee-03bb-4198-8637-d141acf5f289", + "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#minimize-the-use-of-password-based-authentication-for-applications", + "services": [ + "SQL", + "Entra" + ], + "severity": "Medium", + "subcategory": "Azure Active Directory", + "text": "Minimize the use of password-based authentication for applications" + }, + { + "category": "Identity", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "System or User assigned managed identities enable Azure SQLDB to authenticate to other cloud services (e.g. Azure Key Vault) without storing credentials in code. Once enabled, all necessary permissions can be granted via Azure role-based-access-control to the specific Azure SQLDB instance. Do not share user assigned managed identities across multiple services if not strictly required.", + "guid": "69891194-5074-4e30-8f69-4efc3c580900", + "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "services": [ + "ACR", + "AKV", + "Entra", + "SQL", + "RBAC" + ], + "severity": "Low", + "subcategory": "Managed Identities", + "text": "Assign Azure SQL Database a managed identity for outbound resource access" + }, + { + "category": "Identity", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Use an Azure AD integrated authentication that eliminates the use of passwords. Password-based authentication methods are a weaker form of authentication. Credentials can be compromised or mistakenly given away. Use single sign-on authentication using Windows credentials. Federate the on-premises AD domain with Azure AD and use integrated Windows authentication (for domain-joined machines with Azure AD).", + "guid": "88287d4a-8bb8-4640-ad78-03f51354d003", + "link": "https://learn.microsoft.com/azure/azure-sql/database/authentication-aad-configure?view=azuresql&tabs=azure-powershell#active-directory-integrated-authentication", + "services": [ + "SQL", + "Entra" + ], + "severity": "Medium", + "subcategory": "Passwords", + "text": "Minimize the use of password-based authentication for users" + }, + { + "category": "Ledger", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The hash of the latest block in the database ledger is called the database digest. It represents the state of all ledger tables in the database at the time when the block was generated. Generating a database digest is efficient, because it involves computing only the hashes of the blocks that were recently appended. Azure Confidential Ledger is one of the supported store, it can be used and supports automatic generation and storage of database digests. Azure Ledger provides advanced security features like Blockchain Ledger Proof and Confidential Hardware Enclaves. Use it only if advanced security features are required, otherwise revert to Azure storage.", + "guid": "0e853380-50ba-4bce-b2fd-5c7391c85ecc", + "link": "https://learn.microsoft.com/azure/architecture/guide/technology-choices/multiparty-computing-service#confidential-ledger-and-azure-blob-storage", + "services": [ + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": "Database Digest", + "text": "Use Azure Confidential Ledger to store database digests only if advanced security features are required" + }, + { + "category": "Ledger", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The hash of the latest block in the database ledger is called the database digest. It represents the state of all ledger tables in the database at the time when the block was generated. Generating a database digest is efficient, because it involves computing only the hashes of the blocks that were recently appended. Azure Blob Storage with Immutable Storage feature can be used and supports automatic generation and storage of database digests. To prevent tampering of your digest files, configure and lock a retention policy for your container.", + "guid": "afefb2d3-95da-4ac9-acf5-33d18b32ef9a", + "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-digest-management", + "services": [ + "AzurePolicy", + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": "Database Digest", + "text": "If Azure storage account is used to store database digests, ensure security is properly configured" + }, + { + "category": "Ledger", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Ledger provides a form of data integrity called forward integrity, which provides evidence of data tampering on data in your ledger tables. The database verification process takes as input one or more previously generated database digests. It then recomputes the hashes stored in the database ledger based on the current state of the ledger tables. If the computed hashes don't match the input digests, the verification fails. The failure indicates that the data has been tampered with. The verification process reports all inconsistencies that it detects.", + "guid": "f8d4ffda-8aac-4cc6-b72b-c81cb8625420", + "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-database-verification", + "services": [ + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": "Integrity", + "text": "Schedule the Ledger verification process regularly to verify data integrity" + }, + { + "category": "Ledger", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The Ledger feature provides tamper-evidence capabilities in your database. You can cryptographically attest to other parties, such as auditors or other business parties, that your data hasn't been tampered with. Ledger helps protect data from any attacker or high-privileged user, including database administrators (DBAs), system administrators, and cloud administrators.", + "guid": "2563f498-e2d3-42ea-9e7b-5517881a06a2", + "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-overview", + "services": [ + "SQL" + ], + "severity": "Medium", + "subcategory": "Ledger", + "text": "If cryptographic proof of data integrity is a critical requirement, Ledger feature should be considered" + }, + { + "category": "Ledger", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Depending on the type of tampering, there are cases where you can repair the ledger without losing data. In the article contained in the --More Info-- column, different scenarios and recovery techniques are described.", + "guid": "804fc554-6554-4842-91c1-713b32f99902", + "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-how-to-recover-after-tampering", + "services": [ + "SQL" + ], + "severity": "Medium", + "subcategory": "Recovery", + "text": "Prepare a response plan to investigate and repair a database after a tampering event" + }, + { + "category": "Logging", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Azure SQL Database Auditing tracks database events and writes them to an audit log in your Azure storage account. Auditing helps you understand database activity and gain insight into discrepancies and anomalies that could indicate business concerns or suspected security violations as well as helps you meet regulatory compliance. By default auditing policy includes all actions (queries, stored procedures and successful and failed logins) against the databases, which may result in high volume of audit logs. It's recommended for customers to configure auditing for different types of actions and action groups using PowerShell.", + "guid": "4082e31d-35f4-4a49-8507-d3172cc930a6", + "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", + "services": [ + "AzurePolicy", + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": "Auditing", + "text": "Ensure that Azure SQL Database Auditing is enabled at the server level" + }, + { + "category": "Logging", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Azure SQL Database Auditing logs can be written to external storage accounts, Log Analytics workspace or Event Hub. Be sure to protect the target repository using backups and secured configuration. Use Azure SQL Database Managed Identity to access the storage and set an explicit retention period. Do not grant permissions to administrators to the audit log repository. Use a different target storage for --Enabling Auditing of Microsoft support operations--. ", + "guid": "9b64bc50-b60f-4035-bf7a-28c4806dfb46", + "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", + "services": [ + "EventHubs", + "Entra", + "SQL", + "Monitor", + "Storage", + "Backup" + ], + "severity": "Low", + "subcategory": "Auditing", + "text": "Ensure that Azure SQL Database Auditing logs are backed up and secured in the selected repository type" + }, + { + "category": "Logging", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The Azure Monitor activity log is a platform log in Azure that provides insight into subscription-level events. The activity log includes information like when a resource is modified. It is recommended to send this activity log to the same external storage repository as the Azure SQL Database Audit Log (storage account, Log Analytics workspace, Event Hub).", + "guid": "fcd34708-87ac-4efc-aaf6-57a47f76644a", + "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "services": [ + "Subscriptions", + "Storage", + "SQL", + "Monitor", + "EventHubs" + ], + "severity": "Medium", + "subcategory": "Auditing", + "text": "Ensure that Azure SQL Database Activity Log is collected and integrated with Auditing logs" + }, + { + "category": "Logging", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Forward any logs from Azure SQL to your Security Information and Event Management (SIEM) and Security Orchestration Automation and Response (SOAR). Ensure that you are monitoring different types of Azure assets for potential threats and anomalies. Focus on getting high-quality alerts to reduce false positives for analysts to sort through. Alerts can be sourced from log data, agents, or other data.", + "guid": "f96e127e-9572-453a-b325-ff89ae9f6b44", + "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", + "services": [ + "SQL", + "Monitor" + ], + "severity": "Medium", + "subcategory": "SIEM/SOAR", + "text": "Ensure that Azure SQL Database Auditing logs are being presented in to your organizations SIEM/SOAR" + }, + { + "category": "Logging", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Forward any logs from Azure SQL to your Security Information and Event Management (SIEM) and Security Orchestration Automation and Response (SOAR), which can be used to set up custom threat detections. Ensure that you are monitoring different types of Azure assets for potential threats and anomalies. Focus on getting high-quality alerts to reduce false positives for analysts to sort through. Alerts can be sourced from log data, agents, or other data.", + "guid": "41503bf8-73da-4a10-af9f-5f7fceb5456f", + "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "services": [ + "SQL", + "Monitor" + ], + "severity": "Medium", + "subcategory": "SIEM/SOAR", + "text": "Ensure that Azure SQL Database Activity Log data is presented in to your SIEM/SOAR" + }, + { + "category": "Logging", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Security Operation Center (SOC) team should create an incident response plan (playbooks or manual responses) to investigate and mitigate tampering, malicious activities, and other anomalous behaviors.", + "guid": "19ec7c97-c563-4e1d-82f0-54d6ec12e754", + "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "services": [ + "SQL", + "EventHubs" + ], + "severity": "Medium", + "subcategory": "SIEM/SOAR", + "text": "Ensure that you have response plans for malicious or aberrant audit logging events" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "When you create a logical server from the Azure portal for Azure SQL Database, the result is a public endpoint that is visible and reachable over the public network (Public Access). You can then limit connectivity based on firewall rules and Service Endpoint. You can also configure private connectivity only limiting connections to internal networks using Private Endpoint (Private Access). Private Access using Private Endpoint should be the default unless a business case or performance/technical reason applies that cannot support it. Usage of Private Endpoints has performance implications that need to be considered and assessed.", + "guid": "2c6d356a-1784-475b-a42c-ec187dc8c925", + "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview", + "services": [ + "SQL", + "PrivateLink" + ], + "severity": "High", + "subcategory": "Connectivity", + "text": "Review Public vs. Private Access connectivity methods and select the appropriate one for the workload" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "IMPORTANT: Connections to private endpoint only support Proxy as the connection policy. When using private endpoints connections are proxied via the Azure SQL Database gateway to the database nodes. Clients will not have a direct connection.", + "guid": "557b3ce5-bada-4296-8d52-a2d447bc1718", + "link": "https://learn.microsoft.com/azure/azure-sql/database/connectivity-architecture", + "services": [ + "AzurePolicy", + "SQL", + "PrivateLink" + ], + "severity": "Low", + "subcategory": "Connectivity", + "text": "Keep default Azure SQL Database Connection Policy if not differently required and justified" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "This option configures the firewall to allow all connections from Azure, including connections from the subscriptions of other customers. If you select this option, make sure that your login and user permissions limit access to authorized users only. If not strictly required, keep this setting to OFF.", + "guid": "f48efacf-4405-4e8d-9dd0-16c5302ed082", + "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview", + "services": [ + "Subscriptions", + "SQL" + ], + "severity": "High", + "subcategory": "Connectivity", + "text": "Ensure Allow Azure Services and Resources to Access this Server setting is disabled in Azure SQL Database firewall" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Azure SQL Database has a new built-in feature that allows native integration with external REST endpoints. This means that integration of Azure SQL Database with Azure Functions, Azure Logic Apps, Cognitive Services, Event Hubs, Event Grid, Azure Containers, API Management and in general any REST or even GraphQL endpoint. If not properly restricted, code inside an Azure SQL Database database could leverage this mechanism to exfiltrate data. If not strictly required, it is recommended to block or restrict this feature using Outbound Firewall Rules.", + "guid": "cb3274a7-e36d-46f6-8de5-46d30c8dde8e", + "link": "https://learn.microsoft.com/sql/relational-databases/system-stored-procedures/sp-invoke-external-rest-endpoint-transact-sql", + "services": [ + "SQL", + "EventHubs", + "APIM" + ], + "severity": "Medium", + "subcategory": "Outbound Control", + "text": "Block or restrict outbound REST API calls to external endpoints" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Outbound firewall rules limit network traffic from the Azure SQL Database logical server to a customer defined list of Azure Storage accounts and Azure SQL Database logical servers. Any attempt to access storage accounts or databases not in this list is denied.", + "guid": "a566dd3d-314e-4a94-9378-102c42d82b38", + "link": "https://learn.microsoft.com/azure/azure-sql/database/outbound-firewall-rule-overview", + "services": [ + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": "Outbound Control", + "text": "If outbound network access is required, it is recommended to configure outbound networking restrictions using built-in Azure SQL Database control feature" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Private Endpoint is created inside a subnet in an Azure Virtual Network. Proper security configuration must be applied also to the containing network environment, including NSG/ASG, UDR, firewall, monitoring and auditing.", + "guid": "246cd832-f550-4af0-9c74-ca9baeeb8860", + "link": "https://learn.microsoft.com/azure/azure-sql/database/private-endpoint-overview?view=azuresql#disable-public-access-to-your-logical-server", + "services": [ + "PrivateLink", + "SQL", + "Monitor", + "VNet", + "Firewall" + ], + "severity": "Medium", + "subcategory": "Private Access", + "text": "If Private Access connectivity is used, ensure that you are using the Private Endpoint, Azure Virtual Network, Azure Firewall, and Azure Network Security Group checklists" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "When adding a Private Endpoint connection, public routing to your logical server isn't blocked by default. In the --Firewall and virtual networks-- pane, the setting --Deny public network access-- is not selected by default. To disable public network access, ensure that you select --Deny public network access--.", + "guid": "3a0808ee-ea7a-47ab-bdce-920a6a2b3881", + "link": "https://learn.microsoft.com/azure/azure-sql/database/private-endpoint-overview?view=azuresql#disable-public-access-to-your-logical-server", + "services": [ + "VNet", + "SQL", + "PrivateLink" + ], + "severity": "High", + "subcategory": "Private Access", + "text": "If Private Endpoint (Private Access) is used, consider disabling Public Access connectivity" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Network Security Group (NSG) and Application Security Group (ASG) can be now applied to subnet containing Private Endpoints to restrict connections to Azure SQLDB based on internal source IP ranges.", + "guid": "8600527e-e8c4-4424-90ef-1f0dca0224f2", + "link": "https://learn.microsoft.com/azure/private-link/private-endpoint-overview#network-security-of-private-endpoints", + "services": [ + "VNet", + "SQL", + "PrivateLink" + ], + "severity": "Medium", + "subcategory": "Private Access", + "text": "If Private Endpoint (Private Access) is used, apply NSG and eventually ASG to limit incoming source IP address ranges" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "A Managed Instance (SQL MI) can be isolated inside a virtual network to prevent external access. Applications and tools that are in the same or peered virtual network in the same region could access it directly. Applications and tools that are in different region could use virtual-network-to-virtual-network connection or ExpressRoute circuit peering to establish connection. Customer should use Network Security Groups (NSG), and eventually internal firewalls, to restrict access over port 1433 only to resources that require access to a managed instance.", + "guid": "18123ef4-a0a6-45e3-87fe-7f454f65d975", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connectivity-architecture-overview", + "services": [ + "VNet", + "SQL", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Private Access", + "text": "Apply Network Security Groups (NSG) and firewall rules to restrict access to Azure SQL Managed Instance internal subnet" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Azure Virtual Network Service Endpoint is preferred solution if you want to establish a direct connection to the Azure SQL Database backend nodes using Redirect policy. This will allow access in high performance mode and is the recommended approach from a performance perspective.", + "guid": "55187443-6852-4fbd-99c6-ce303597ca7f", + "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview?view=azuresql#ip-vs-virtual-network-firewall-rules", + "services": [ + "AzurePolicy", + "VNet", + "SQL" + ], + "severity": "High", + "subcategory": "Public Access", + "text": "If Public Access connectivity is used, leverage Service Endpoint to restrict access from selected Azure Virtual Networks" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The Azure SQL Database firewall allows you to specify IP address ranges from which communications are accepted. This approach is fine for stable IP addresses that are outside the Azure private network.", + "guid": "a73e32da-b3f4-4960-b5ec-2f42a557bf31", + "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview", + "services": [ + "SQL", + "Storage" + ], + "severity": "Medium", + "subcategory": "Public Access", + "text": "If Public Access connectivity is used, ensure that only specific known IPs are added to the firewall" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "We recommend that you use database-level IP firewall rules whenever possible. This practice enhances security and makes your database more portable. Use server-level IP firewall rules for administrators. Also use them when you have many databases that have the same access requirements, and you don't want to configure each database individually.", + "guid": "e0f31ac9-35c8-4bfd-9865-edb60ffc6768", + "link": "https://learn.microsoft.com/azure/azure-sql/database/firewall-configure", + "services": [ + "SQL", + "Storage" + ], + "severity": "Low", + "subcategory": "Public Access", + "text": "If Public Access connectivity is used and controlled by Azure SQL Database firewall rules, use database-level over server-level IP rules" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "A Managed Instance (SQL MI) can be isolated inside a virtual network to prevent external access. The Managed Instance public endpoint is not enabled by default, must be explicitly enabled, only if strictly required. If company policy disallows the use of public endpoints, use Azure Policy to prevent enabling public endpoints in the first place.", + "guid": "b8435656-143e-41a8-9922-61d34edb751a", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/public-endpoint-overview", + "services": [ + "AzurePolicy", + "VNet", + "SQL" + ], + "severity": "High", + "subcategory": "Public Access", + "text": "Do not enable Azure SQL Managed Instance public endpoint" + }, + { + "category": "Networking", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "A Managed Instance (SQL MI) public endpoint is not enabled by default, must be explicitly enabled, only if strictly required. In this case, it is recommended to apply a Network Security Groups (NSG) to restrict access to port 3342 only to trusted source IP addresses.", + "guid": "057dd298-8726-4aa6-b590-1f81d2e30421", + "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/public-endpoint-overview", + "services": [ + "VNet", + "SQL" + ], + "severity": "High", + "subcategory": "Public Access", + "text": "Restrict access if Azure SQL Managed Instance public endpoint is required" + }, + { + "category": "Privileged Access", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Most operations, support, and troubleshooting performed by Microsoft personnel and sub-processors do not require access to customer data. In those rare circumstances where such access is required, Customer Lockbox for Microsoft Azure provides an interface for customers to review and approve or reject customer data access requests. In support scenarios where Microsoft needs to access customer data, Azure SQL Database supports Customer Lockbox to provide an interface for you to review and approve or reject customer data access requests.", + "guid": "37b6eb0f-553d-488f-8a8a-cb9bf97388ff", + "link": "https://learn.microsoft.com/azure/security/fundamentals/customer-lockbox-overview", + "services": [ + "SQL" + ], + "severity": "Low", + "subcategory": "Lockbox", + "text": "Review and enable Customer Lockbox for Azure SQL Database access by Microsoft personnel" + }, + { + "category": "Privileged Access", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "The principle of least privilege states that users shouldn't have more privileges than needed to complete their tasks. High-privileged database and server users can perform many configuration and maintenance activities on the database and can also drop databases in Azure SQL instance. Tracking database owners and privileged accounts is important to avoid having excessive permission.", + "guid": "5fe5281f-f0f9-4842-a682-8baf18bd8316", + "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#implement-principle-of-least-privilege", + "services": [ + "SQL" + ], + "severity": "Medium", + "subcategory": "Permissions", + "text": "Ensure that users are assigned the minimum level of access necessarily to complete their job functions" + }, + { + "category": "Privileged Access", + "checklist": "Azure SQLDB Security Checklist (Preview)", + "description": "Identities (both Users and SPNs) should be scoped to the least amount of access needed to perform the function. A higher number of tightly scoped SPNs should be used, instead of having one SPN with multiple sets of unrelated permissions. For example, if there are three external web applications hosted on-prem that make queries to the Azure SQL Database, they should not all use the same SPN for these activities. Instead, they should each have their own tightly scoped SPN.", + "guid": "7b5b55e5-4750-4920-be97-eb726c256a5c", + "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#im-3-use-azure-ad-single-sign-on-sso-for-application-access", + "services": [ + "SQL", + "Entra" + ], + "severity": "Low", + "subcategory": "Permissions", + "text": "Ensure that distinct applications will be assigned different credentials with minimal permissions to access Azure SQL Database" + }, + { + "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": [ + "Cost", + "Monitor" + ], + "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": "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": [ + "Cost", + "Backup" + ], + "subcategory": "Backup", + "text": "check backup instances with the underlying datasource not found" + }, + { + "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": "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": [ + "Cost" + ], + "subcategory": "delete/archive", + "text": "consider snooze and stop technique (snooze a service after x days, stop after 2x, delete/deallocate after 3x)" + }, + { + "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": [ + "Cost", + "Storage", + "Backup" + ], + "subcategory": "delete/archive", + "text": "delete or archive unused resources (old backups, logs, storage accounts, etc...)" + }, + { + "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": [ + "Cost", + "ASR", + "Backup", + "Storage" + ], + "subcategory": "delete/archive", + "text": "consider a good balance between site recovery storage and backup for non mission critical applications" + }, + { + "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": [ + "Cost", + "Monitor" + ], + "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": "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": [ + "AzurePolicy", + "Cost", + "Storage" + ], + "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": "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": "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": "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", + "Storage", + "Backup", + "VM" + ], + "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": "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": [ + "AzurePolicy", + "Cost", + "Storage" + ], + "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": "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": "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": "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": "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": [ + "Cost", + "Storage", + "VM" + ], + "subcategory": "db optimization", + "text": "optimizing the DB queries will increase performance and allow better right-sizing of storage and VMs" + }, + { + "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": [ + "Cost" + ], + "subcategory": "demand shaping", + "text": "using demand shaping on PaaS services will optimize costs and performances" + }, + { + "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": "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": [ + "Cost", + "VM" + ], + "subcategory": "Advisor", + "text": "make sure advisor is configured for VM right sizing " + }, + { + "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" + ], + "subcategory": "Automation", + "text": "consider implementing IAC scripts or devops pipelines to match the cost governance process" + }, + { + "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": [ + "Cost", + "Monitor" + ], + "subcategory": "Automation", + "text": "set up cost alerts for applications that have variable costs (ideally for all of them)" + }, + { + "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": [ + "Cost" + ], + "subcategory": "Automation", + "text": "Use Azure Automation: Automate repetitive tasks can help you save time and resources, reducing costs in the process. " + }, + { + "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": [ + "Cost" + ], + "subcategory": "Automation", + "text": "run orphaned resources workbook" + }, + { + "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": [ + "Cost", + "Storage" + ], + "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": "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": [ + "AzurePolicy", + "Cost" + ], + "subcategory": "Baseline", + "text": "establish a cost optimization baseline by using a policy that tags every new resource as #NEW" + }, + { + "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": "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": [ + "Cost" + ], + "subcategory": "Budgets", + "text": "Create budgets" + }, + { + "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": "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": "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": "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": "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": [ + "Cost" + ], + "subcategory": "Tagging", + "text": "Tag shared resources" + }, + { + "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": "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": [ + "Cost" + ], + "subcategory": "automation", + "text": "consider Reservation automation to track and promptly react to changes" + }, + { + "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": [ + "AzurePolicy", + "Cost", + "SQL", + "VM" + ], + "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": "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": [ + "Cost", + "LoadBalancer" + ], + "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": "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" + ], + "subcategory": "Functions", + "text": "saving plans will provide 17% on select app service plans" + }, + { + "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": [ + "Cost", + "VM" + ], + "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": "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": [ + "Cost", + "ARS", + "VM" + ], + "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": "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": [ + "Cost" + ], + "subcategory": "reservations/savings plans", + "text": "plan for Azure Savings Plans for all the workloads that are dynamic and need maximum flexibility" + }, + { + "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": [ + "Cost" + ], + "subcategory": "reservations/savings plans", + "text": "plan for Azure Reservations for all the workloads that are less dynamic and won't change much" + }, + { + "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": [ + "Cost", + "Storage" + ], + "subcategory": "reserve storage", + "text": "only larger disks can be reserved =>1TiB -" + }, + { + "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": [ + "Cost", + "VM" + ], + "subcategory": "reserve VMs with normalized and rationalized sizes", + "text": "after the right-sizing optimization" + }, + { + "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": [ + "AzurePolicy", + "Cost", + "SQL" + ], + "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": "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": [ + "Cost", + "SQL", + "VM" + ], + "subcategory": "SQL Database Reservations", + "text": "the VM + licence part discount (ahub+3YRI) is around 70% discount" + }, + { + "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": [ + "Cost" + ], + "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": "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": [ + "AzurePolicy", + "Cost" + ], + "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": "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": [ + "AzurePolicy", + "Cost" + ], + "subcategory": "Automation", + "text": "plan and enforce a ON/OFF policy for production services, where possible" + }, + { + "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": [ + "AzurePolicy", + "Cost" + ], + "subcategory": "Automation", + "text": "plan and enforce a ON-DEMAND policy with auto-shutdown for non-production services, where possible" + }, + { + "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": [ + "Cost", + "VM" + ], + "subcategory": "Autoscale", + "text": "consider using a VMSS to match demand rather than flat sizing" + }, + { + "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": [ + "Cost", + "AKS" + ], + "subcategory": "Autoscale", + "text": "use AKS autoscaler to match your clusters usage (make sure the pods requirements match the scaler)" + }, + { + "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": [ + "Cost" + ], + "subcategory": "Autoscale", + "text": "right-size PaaS service according to average use and accomodate spikes with auto or manual scaling" + }, + { + "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": [ + "Cost" + ], + "subcategory": "Autoscale", + "text": "plan for demand shaping where applicable" + }, + { + "category": "Right-sizing", + "checklist": "Cost Optimization Checklist", + "guid": "e2e8aaab-3571-4549-ab91-53d89f89dc7b", + "id": "E02.05", + "services": [ + "Cost" + ], + "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": "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": [ + "Cost", + "Backup" + ], + "subcategory": "Backup", + "text": "Move recovery points to vault-archive where applicable (Validate)", + "training": "https://azure.microsoft.com/pricing/reservations/" + }, + { + "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": [ + "Cost", + "VM", + "LoadBalancer" + ], + "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": "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": [ + "Cost" + ], + "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": "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": [ + "Cost" + ], + "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": [ + "Cost", + "Storage" + ], + "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": "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": [ + "Cost" + ], + "subcategory": "Functions", + "text": "Functions -Keep your functions warm", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-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", + "services": [ + "Cost" + ], + "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": "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": [ + "Cost" + ], + "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": "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": [ + "Cost" + ], + "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": "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": [ + "Cost" + ], + "subcategory": "Networking", + "text": "evaluate your network topology against networking costs and where applicable reduce the egress and peering data" + }, + { + "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": [ + "Cost", + "EventHubs", + "FrontDoor" + ], + "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": "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": [ + "Cost", + "AppSvc", + "FrontDoor" + ], + "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": "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": [ + "Cost" + ], + "subcategory": "PaaS", + "text": "consider using free tiers where applicable for all non-production environments" + }, + { + "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": [ + "Cost" + ], + "subcategory": "serverless", + "text": "using serverless patterns for spikes can help keeping costs down" + }, + { + "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": [ + "Cost", + "Storage" + ], + "subcategory": "Storage", + "text": "consider archiving tiers for less used data" + }, + { + "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": [ + "Cost", + "Storage" + ], + "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": "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": [ + "Cost", + "Storage" + ], + "subcategory": "Storage", + "text": "consider using standard SSD rather than Premium or Ultra where possible" + }, + { + "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": [ + "Cost", + "Storage" + ], + "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": "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": [ + "Cost", + "ASR", + "Storage" + ], + "subcategory": "Storage", + "text": "for ASR, consider using Standard SSD disks if the RPO/RTO and replication throughput allow it" + }, + { + "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": [ + "Cost", + "Storage" + ], + "subcategory": "storage", + "text": "storage accounts: check hot tier and/or GRS necessary" + }, + { + "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": [ + "Cost", + "Storage" + ], + "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": "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": [ + "Cost", + "EventHubs", + "Monitor" + ], + "subcategory": "Synapse", + "text": "Create budgets to manage costs and create alerts that automatically notify stakeholders of spending anomalies and overspending risks." + }, + { + "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": [ + "Cost", + "Storage" + ], + "subcategory": "Synapse", + "text": "Export cost data to a storage account for additional data analysis." + }, + { + "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": [ + "Cost", + "SQL" + ], + "subcategory": "Synapse", + "text": "Control costs for a dedicated SQL pool by pausing the resource when it is not in use." + }, + { + "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": [ + "Cost" + ], + "subcategory": "Synapse", + "text": "Enable the serverless Apache Spark automatic pause feature and set your timeout value accordingly." + }, + { + "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": [ + "Cost" + ], + "subcategory": "Synapse", + "text": "Create multiple Apache Spark pool definitions of various sizes." + }, + { + "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": [ + "Cost" + ], + "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": "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": [ + "Cost", + "VM" + ], + "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": "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": [ + "Cost", + "VM" + ], + "subcategory": "VM", + "text": "right-sizing all VMs" + }, + { + "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": [ + "Cost", + "VM" + ], + "subcategory": "VM", + "text": "swap VM sized with normalized and most recent sizes", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/" + }, + { + "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": [ + "Cost", + "Monitor", + "VM" + ], + "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": "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": [ + "Cost", + "VM" + ], + "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": "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", + "link": "https://azure.microsoft.com/support/legal/sla/virtual-desktop/v1_0/", + "services": [ + "Subscriptions", + "ASR", + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Compute", + "text": "Determine the expected High Availability SLA for applications/desktops published through AVD" + }, + { + "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/en-us/fslogix/concepts-container-recovery-business-continuity.", + "guid": "6acc076e-f9b1-441a-a989-579e76b897e7", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/azure-virtual-desktop-multi-region-bcdr", + "services": [ + "ASR", + "Storage", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Compute", + "text": "Assess Geo Disaster Recovery requirements for AVD Host Pools" + }, + { + "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 are 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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "services": [ + "ASR", + "AVD" + ], + "severity": "Low", + "subcategory": "Compute", + "text": "Separate critical applications in different AVD Host Pools" + }, + { + "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/en-us/azure/virtual-machines/availability.", + "guid": "25ab225c-6f4e-4168-9fdd-dea8a4b7cdeb", + "link": "https://techcommunity.microsoft.com/t5/azure-virtual-desktop-blog/announcing-general-availability-of-support-for-azure/ba-p/3636262", + "services": [ + "ACR", + "ASR", + "AVD" + ], + "severity": "High", + "subcategory": "Compute", + "text": "Plan the best resiliency option for AVD Host Pool deployment" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "services": [ + "ASR", + "Backup", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Compute", + "text": "Assess the requirement to backup AVD Session Host VMs" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/site-recovery/azure-to-azure-how-to-enable-zone-to-zone-disaster-recovery", + "services": [ + "ASR", + "VM", + "Cost", + "AVD", + "Backup" + ], + "severity": "Medium", + "subcategory": "Compute", + "text": "Prepare a local DR strategy for Personal Host Pool Session Hosts" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-machines/azure-compute-gallery", + "services": [ + "ACR", + "ASR", + "VM", + "AVD", + "Storage" + ], + "severity": "Low", + "subcategory": "Dependencies", + "text": "Plan for Golden Image cross-region availability" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "services": [ + "ASR", + "AVD" + ], + "severity": "Medium", + "subcategory": "Dependencies", + "text": "Assess Infrastructure & Application dependencies " + }, + { + "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", + "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt", + "services": [ + "ASR", + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Assess which data need to be protected in the Profile and Office Containers" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "services": [ + "ASR", + "AzurePolicy", + "AVD", + "Storage", + "Backup" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Build a backup protection strategy for Profile and Office Containers" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/disaster-recovery", + "services": [ + "ASR", + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Assess Profile Container storage replication requirements and resiliency for BCDR purpose" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/backup/backup-afs", + "services": [ + "ASR", + "Backup", + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Review Azure Files disaster recovery strategy" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/storage/files/files-redundancy#zone-redundant-storage", + "services": [ + "ASR", + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "Storage", + "text": "Use Zone Redundant Storage (ZRS) for Azure Files to maximize resiliency" + }, + { + "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/en-us/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/en-us/azure/azure-netapp-files/manage-availability-zone-volume-placement.", + "guid": "23429db7-2281-4376-85cc-57b4a4b18142", + "link": "https://learn.microsoft.com/azure/azure-netapp-files/cross-region-replication-create-peering", + "services": [ + "ACR", + "ASR", + "AVD", + "Storage", + "Backup" + ], + "severity": "Medium", + "subcategory": "Storage", + "text": "Review Azure NetApp Files disaster recovery strategy" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "services": [ + "AVD" + ], + "severity": "High", + "subcategory": "Golden Images", + "text": "Determine how applications will be deployed in AVD Host Pools" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Golden Images", + "text": "Estimate the number of golden images that will be required" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#operating-systems-and-licenses", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Golden Images", + "text": "Determine which OS image/s you will use for Host Pool deployment" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-machines/shared-image-galleries", + "services": [ + "Storage", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Select the proper store for custom images" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/create-custom-image-templates", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Design your build process for custom images" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-golden-image", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Golden Images", + "text": "If custom image will be used, check recommended best practices for AVD on how to build custom image" + }, + { + "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", + "link": "https://learn.microsoft.com/fslogix/how-to-install-fslogix", + "services": [ + "AVD" + ], + "severity": "High", + "subcategory": "Golden Images", + "text": "Include the latest version of FSLogix in the golden image update process" + }, + { + "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", + "link": "https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool", + "services": [ + "RBAC", + "AVD" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Evaluate the usage of Virtual-Desktop-Optimization-Tool" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/install-office-on-wvd-master-image#install-onedrive-in-per-machine-mode", + "services": [ + "Storage", + "AVD" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Determine if Microsoft OneDrive will be part of AVD deployment" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/teams-on-AVD", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Golden Images", + "text": "Determine if Microsoft Teams will be part of AVD deployment" + }, + { + "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", + "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" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "services": [ + "Cost", + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Do not use the same storage account/share as FSLogix profiles" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Review performance considerations for MSIX" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-file-share", + "services": [ + "Storage", + "RBAC", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Check proper session host permissions for MSIX share" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "MSIX & AppAttach", + "text": "MSIX packages for 3rd-party applications" + }, + { + "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", + "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" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/app-attach-faq", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "MSIX & AppAttach", + "text": "Review operating systems support" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-machines/generation-2", + "services": [ + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Session Host", + "text": "Evaluate the usage of Gen2 VM for Host Pool deployment" + }, + { + "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", + "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" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology#host-pools", + "services": [ + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Determine the Host Pool type to use" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#host-pools", + "services": [ + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Estimate the number of different Host Pools to deploy " + }, + { + "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", + "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" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/host-pool-load-balancing", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "For Pooled Host Pool type, select the best load balancing method" + }, + { + "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", + "link": "https://learn.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "services": [ + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Capacity Planning", + "text": "For Pooled Host Pool type, VMs shouldn't have more than 32 cores" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/terminology?WT.mc_id=Portal-fx#application-groups", + "services": [ + "Storage", + "AVD" + ], + "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" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-virtual-desktop-service-limits", + "services": [ + "ACR", + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Capacity Planning", + "text": "Estimate the number of Application Groups required across all Host Pools in the Microsoft Entra ID tenant" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Estimate the number of Applications for each Application Group" + }, + { + "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", + "link": "https://learn.microsoft.com/en-us/azure/virtual-desktop/configure-host-pool-personal-desktop-assignment-type?tabs=azure#reassign-a-personal-desktop", + "services": [ + "Storage", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Evaluate the usage of FSLogix for Personal Host Pools" + }, + { + "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", + "link": "https://docs.microsoft.com/windows-server/remote/remote-desktop-services/virtual-machine-recs", + "services": [ + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Run workload performance test to determine the best Azure VM SKU and size to use" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/architecture/example-scenario/wvd/windows-virtual-desktop#considerations", + "services": [ + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Verify AVD scalability limits for the environment" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/configure-vm-gpu", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Determine if Session Hosts will require GPU" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview", + "services": [ + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Capacity Planning", + "text": "Use Azure VM SKUs able to leverage Accelerated Networking" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/overview", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Clients & Users", + "text": "Assess how many users will connect to AVD and from which regions" + }, + { + "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", + "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": [ + "Storage", + "VPN", + "ExpressRoute", + "AVD" + ], + "severity": "Medium", + "subcategory": "Clients & Users", + "text": "Assess external dependencies for each Host Pool" + }, + { + "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", + "link": "https://learn.microsoft.com/en-us/azure/virtual-desktop/users/connect-windows", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Clients & Users", + "text": "Review user client OS used and AVD client type" + }, + { + "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", + "link": "https://azure.microsoft.com/services/virtual-desktop/assessment/", + "services": [ + "AVD" + ], + "severity": "High", + "subcategory": "Clients & Users", + "text": "Run a PoC to validate end-to-end user experience and impact of network latency" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/customize-rdp-properties", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Clients & Users", + "text": "Assess and document RDP settings for all user groups" + }, + { + "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", + "link": "https://azure.microsoft.com/global-infrastructure/services/?products=virtual-desktop", + "services": [ + "AVD" + ], + "severity": "High", + "subcategory": "General", + "text": "Determine in which Azure regions AVD Host Pools will be deployed." + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/data-locations", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "General", + "text": "Determine metadata location for AVD service" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", + "services": [ + "Storage", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "General", + "text": "Check Azure quotas and availability for specific VM sizes and types in the selected regions" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", + "services": [ + "VNet", + "Storage", + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Create at least two Active Directory Domain Controllers (DCs) in Azure VNet environment close to AVD Host Pool" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/create-host-pools-azure-marketplace", + "services": [ + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Create a specific OU in Active Directory for each Host Pool" + }, + { + "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", + "link": "https://docs.microsoft.com/previous-versions/windows/desktop/Policy/group-policy-hierarchy", + "services": [ + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Review Domain GPOs that will be applied to OU and impacting Host Pool Session Hosts functionalities" + }, + { + "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", + "link": "https://learn.microsoft.com/fslogix/how-to-use-group-policy-templates", + "services": [ + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Configure FSLogix settings using the built-in provided GPO ADMX template" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#session-hosts", + "services": [ + "Entra", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Create a dedicated user account with only permissions to join VM to the domain" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/manage-app-groups", + "services": [ + "Entra", + "AVD" + ], + "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)" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/storage/files/storage-files-identity-ad-ds-enable", + "services": [ + "AzurePolicy", + "Storage", + "Entra", + "AVD" + ], + "severity": "High", + "subcategory": "Active Directory", + "text": "Review your organization password expiration policy for accounts used by Azure Files AD integration" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", + "services": [ + "Entra", + "AVD" + ], + "severity": "High", + "subcategory": "Active Directory", + "text": "A Windows Server Active Directory forest/domain must be in sync with Microsoft Entra ID" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-identity-auth-hybrid-identities-enable", + "services": [ + "Storage", + "Entra", + "AVD" + ], + "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" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#identity", + "services": [ + "Subscriptions", + "VNet", + "Entra", + "AVD" + ], + "severity": "High", + "subcategory": "Requirements", + "text": "A Microsoft Entra ID tenant must be available with at least one subscription linked" + }, + { + "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/en-us/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios.", + "guid": "b4ce4781-7557-4a1f-8043-332ae199d44c", + "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication", + "services": [ + "Entra", + "AVD" + ], + "severity": "High", + "subcategory": "Requirements", + "text": "Review and document your identity scenario" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "services": [ + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Requirements", + "text": "Assess User Account types and requirements" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/authentication#single-sign-on-sso", + "services": [ + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Requirements", + "text": "If Single-Sign On (SSO) is a requirement, review the supported scenarios and prerequisites" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/prerequisites?tabs=portal#supported-identity-scenarios", + "services": [ + "Entra", + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Requirements", + "text": "Select the proper AVD Session Host domain join type" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/active-directory-domain-services/compare-identity-solutions", + "services": [ + "Entra", + "AVD" + ], + "severity": "Low", + "subcategory": "Requirements", + "text": "Before using Azure AD Domain Services (AAD-DS) for AVD, be sure to review the limitations." + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/administrative-template", + "services": [ + "Monitor", + "Entra", + "AVD" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Use built-in provided administrative templates for AVD settings configuration" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/management", + "services": [ + "Monitor", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Plan AVD Session Hosts configuration management strategy" + }, + { + "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/en-us/mem/intune/fundamentals/windows-virtual-desktop and multi-session https://learn.microsoft.com/en-us/mem/intune/fundamentals/windows-virtual-desktop-multi-session AVD.", + "guid": "63a08be1-6004-4b4a-a79b-f3239faae113", + "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop", + "services": [ + "Monitor", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Evaluate Intune for AVD Session Hosts management" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/autoscale-scenarios", + "services": [ + "Cost", + "Monitor", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Assess the requirements for host pool auto-scaling capability" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect", + "services": [ + "Cost", + "Monitor", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Consider the usage of Start VM on Connect for Personal Host Pools" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/start-virtual-machine-connect-faq#are-vms-automatically-deallocated-when-a-user-stops-using-them", + "services": [ + "VM", + "AzurePolicy", + "Cost", + "AVD", + "Monitor" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Evaluate the implementation of an ad-hoc mechanism to shut down Personal AVD Session Hosts" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/tag-virtual-desktop-resources", + "services": [ + "Cost", + "VPN", + "AVD", + "Monitor", + "VWAN", + "Storage", + "ExpressRoute", + "DNS" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Review and adopt suggested Azure Tags for Azure Virtual Desktop" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/azure-advisor-recommendations", + "services": [ + "Cost", + "Monitor", + "Entra", + "AVD" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Periodically check Azure Advisor recommendations for AVD" + }, + { + "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/en-us/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/en-us/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", + "link": "https://learn.microsoft.com/mem/intune/fundamentals/azure-virtual-desktop-multi-session", + "services": [ + "Monitor", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Plan for a Session Host emergency patching and update strategy" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/scheduled-agent-updates", + "services": [ + "Monitor", + "AVD" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Configure the Scheduled Agent Updates feature" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/create-validation-host-pool", + "services": [ + "Monitor", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Create a validation (canary) Host Pool" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-platform-automation-and-devops", + "services": [ + "Monitor", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Determine Host Pool deployment strategy" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/faq", + "services": [ + "Monitor", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Turn on Session Host VMs at least every 90 days for token refresh" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/insights", + "services": [ + "Monitor", + "AVD" + ], + "severity": "High", + "subcategory": "Monitoring", + "text": "Enable monitoring for AVD" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/diagnostics-log-analytics", + "services": [ + "Monitor", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Enable diagnostic settings for Workspaces, Host Pools, Application Groups and Host VMs to Log Analytics workspace" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/storage/files/storage-files-monitoring?tabs=azure-portal", + "services": [ + "Storage", + "Monitor", + "AVD" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Create alerts on the profile storage to be alerted in case of high usage and throttling" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/set-up-service-alerts", + "services": [ + "Monitor", + "AVD" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Configure Azure Service Health for AVD alerts " + }, + { + "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", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "services": [ + "NVA", + "VPN", + "ExpressRoute", + "AVD" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Determine if hybrid connectivity is required to connect to on-premises environment" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/wvd/eslz-network-topology-and-connectivity", + "services": [ + "VNet", + "VWAN", + "AVD" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Determine Azure Virtual Network (VNet) placement for each AVD Host Pool" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/", + "services": [ + "VPN", + "AVD" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Assess which on-premises resources are required from AVD Host Pools" + }, + { + "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", + "link": " https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "services": [ + "VNet", + "NVA", + "Firewall", + "AVD" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Need to control/restrict Internet outbound traffic for AVD hosts?" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/safe-url-list", + "services": [ + "AVD" + ], + "severity": "High", + "subcategory": "Networking", + "text": "Ensure AVD control plane endpoints are accessible" + }, + { + "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", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/onboard-windows-multi-session-device?view=o365-worldwide", + "services": [ + "Defender", + "AVD" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Need to control/restrict Internet outbound traffic only for users on AVD hosts? " + }, + { + "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/en-us/azure/virtual-desktop/safe-url-list.", + "guid": "523181a9-4174-4158-93ff-7ae7c6d37431", + "link": "https://docs.microsoft.com/azure/firewall/protect-windows-virtual-desktop", + "services": [ + "VNet", + "NVA", + "Firewall", + "AVD" + ], + "severity": "Low", + "subcategory": "Networking", + "text": "Review custom UDR and NSG for AVD Host Pool subnets" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/proxy-server-support", + "services": [ + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Networking", + "text": "Do not use Proxy servers, SSL termination and Deep Packet Inspection for AVD control plane traffic" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/rdp-bandwidth", + "services": [ + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Networking", + "text": "Check the network bandwidth required for each user and in total for the VM SKU" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-networking-endpoints", + "services": [ + "Cost", + "PrivateLink", + "AVD", + "VNet", + "Storage" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Evaluate usage Private Endpoint for Azure Files share" + }, + { + "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/en-us/azure/virtual-desktop/rdp-shortpath?tabs=managed-networks#key-benefits.", + "guid": "b2074747-d01a-4f61-b1aa-92ad793d9ff4", + "link": "https://docs.microsoft.com/azure/virtual-desktop/shortpath", + "services": [ + "VPN", + "AVD" + ], + "severity": "Medium", + "subcategory": "Networking", + "text": "Evaluate usage of RDP ShortPath for clients connecting from managed internal networks" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#establish-maximum-inactive-time-and-disconnection-policies", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Active Directory", + "text": "Review Active Directory GPO to secure RDP sessions" + }, + { + "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", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/deployment-vdi-microsoft-defender-antivirus", + "services": [ + "Defender", + "AVD" + ], + "severity": "High", + "subcategory": "Host Configuration", + "text": "Ensure anti-virus and anti-malware solutions are used" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-machines/disk-encryption-overview", + "services": [ + "AKV", + "Storage", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "Host Configuration", + "text": "Assess disk encryption requirements for AVD Session Hosts" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#azure-virtual-desktop-support-for-trusted-launch", + "services": [ + "Monitor", + "VM", + "AVD" + ], + "severity": "Medium", + "subcategory": "Host Configuration", + "text": "Enable Trusted launch in Azure Gen2 VM Session Hosts" + }, + { + "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", + "link": "https://learn.microsoft.com/windows/whats-new/windows-11-requirements", + "services": [ + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Host Configuration", + "text": "Enable Trusted Launch and use Gen2 image are system requirements for Windows 11" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/screen-capture-protection", + "services": [ + "AVD" + ], + "severity": "Low", + "subcategory": "Host Configuration", + "text": "Consider enabling screen capture protection to prevent sensitive information from being captured" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#other-security-tips-for-session-hosts", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Host Configuration", + "text": "Restrict device redirection and drive mapping" + }, + { + "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", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "When possible, prefer Remote Apps over Full Desktops (DAG)" + }, + { + "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", + "link": "https://learn.microsoft.com/microsoft-365/security/defender-endpoint/web-protection-overview", + "services": [ + "Defender", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Need to control/restrict user Internet navigation from AVD session hosts?" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/security-guide", + "services": [ + "AVD" + ], + "severity": "High", + "subcategory": "Management", + "text": "Ensure AVD users will not have local administrator privileges on AVD Hosts" + }, + { + "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/en-us/azure/virtual-desktop/security-guide#improve-your-secure-score.", + "guid": "1814387e-5ca9-4c26-a9b3-2ab5bdfc6998", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#enable-microsoft-defender-for-cloud", + "services": [ + "Subscriptions", + "VM", + "AKV", + "Storage", + "AVD", + "Defender" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Enable Microsoft Defender for Cloud to manage AVD Session Hosts security posture" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#collect-audit-logs", + "services": [ + "Monitor", + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Enable diagnostic and audit logging" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/rbac", + "services": [ + "RBAC", + "Entra", + "AVD" + ], + "severity": "Low", + "subcategory": "Management", + "text": "Assess the requirement to use custom RBAC roles for AVD management" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/security-guide#windows-defender-application-control", + "services": [ + "Defender", + "AVD" + ], + "severity": "Medium", + "subcategory": "Management", + "text": "Restrict users from installing un-authorized applications" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/set-up-mfa", + "services": [ + "Entra", + "AVD" + ], + "severity": "Medium", + "subcategory": "Microsoft Entra ID", + "text": "Evaluate the usage of Multi-Factor Authentication (MFA) and Conditional Access (CA) for AVD users" + }, + { + "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", + "link": "https://learn.microsoft.com/security/zero-trust/azure-infrastructure-avd", + "services": [ + "AVD" + ], + "severity": "Medium", + "subcategory": "Zero Trust", + "text": "Review and Apply Zero Trust principles and guidance" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files#best-practices-for-azure-virtual-desktop", + "services": [ + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Azure Files", + "text": "Check best-practices for Azure Files" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/storage/files/storage-files-smb-multichannel-performance", + "services": [ + "ACR", + "Cost", + "Storage", + "AVD" + ], + "severity": "Low", + "subcategory": "Azure Files", + "text": "Enable SMB multichannel when using a premium file share to host FSLogix profile containers." + }, + { + "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", + "link": "https://azure.microsoft.com/global-infrastructure/services/", + "services": [ + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Azure NetApp Files", + "text": "If NetApp Files storage is required, check storage service availability in your specific region." + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/create-fslogix-profile-container", + "services": [ + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Azure NetApp Files", + "text": "If NetApp Files storage is used enable CA (Continuous Availability) option to increase resiliency" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/azure-netapp-files/create-active-directory-connections", + "services": [ + "VNet", + "Storage", + "AVD" + ], + "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" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-machines/disks-types", + "services": [ + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "Capacity Planning", + "text": "Determine which type of managed disk will be used for the Session Hosts" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "services": [ + "Storage", + "VM", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Determine which storage backend solution will be used for FSLogix Profiles" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/store-fslogix-profile", + "services": [ + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Do not share storage and profiles between different Host Pools" + }, + { + "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", + "link": "https://learn.microsoft.com/azure/virtual-desktop/faq#what-s-the-largest-profile-size-fslogix-can-handle-", + "services": [ + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "Verify storage scalability limits and Host Pool requirements" + }, + { + "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", + "link": "https://docs.microsoft.com/azure/virtual-desktop/fslogix-containers-azure-files", + "services": [ + "Cost", + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "Capacity Planning", + "text": "For optimal performance, the storage solution and the FSLogix profile container should be in the same Azure region." + }, + { + "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", + "link": "https://learn.microsoft.com/fslogix/concepts-container-types#when-to-use-profile-and-odfc-containers", + "services": [ + "ASR", + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "FSLogix", + "text": "Do not use Office Containers (ODFC) if not strictly required and justified" + }, + { + "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", + "link": "https://learn.microsoft.com/fslogix/overview-prerequisites#configure-antivirus-file-and-folder-exclusions", + "services": [ + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "FSLogix", + "text": "Configure the recommended antivirus exclusions for FSLogix (includes not scanning VHD(x) files on connect)." + }, + { + "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", + "link": "https://docs.microsoft.com/fslogix/profile-container-configuration-reference", + "services": [ + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "FSLogix", + "text": "Review and confirm configured maximum profile size in FSLogix" + }, + { + "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", + "link": "https://learn.microsoft.com/fslogix/concepts-configuration-examples", + "services": [ + "ACR", + "Storage", + "AKV", + "AVD" + ], + "severity": "High", + "subcategory": "FSLogix", + "text": "Review FSLogix registry keys and determine which ones to apply" + }, + { + "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", + "link": "https://learn.microsoft.com/fslogix/concepts-multi-concurrent-connections", + "services": [ + "Storage", + "AVD" + ], + "severity": "High", + "subcategory": "FSLogix", + "text": "Avoid usage of concurrent or multiple connections" + }, + { + "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/en-us/fslogix/concepts-fslogix-cloud-cache. ", + "guid": "b2d1215a-e114-4ba3-9df5-85ecdcd9bd3b", + "link": "https://docs.microsoft.com/fslogix/cloud-cache-configuration-reference", + "services": [ + "Storage", + "VM", + "AVD" + ], + "severity": "Low", + "subcategory": "FSLogix", + "text": "If FSLogix Cloud Cache is used, consider moving the cache directory to the VM temporary drive." + }, + { + "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", + "link": "https://docs.microsoft.com/fslogix/manage-profile-content-cncpt#redirectionsxml", + "services": [ + "Storage", + "AVD" + ], + "severity": "Medium", + "subcategory": "FSLogix", + "text": "Review the usage of FSLogix redirection." + }, + { + "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": [ + "Entra" + ], + "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": "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": [ + "Entra" + ], + "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": "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": [ + "Entra" + ], + "severity": "Low", + "subcategory": "Microsoft Entra ID Tenants", + "text": "Leverage Azure Lighthouse for Multi-Tenant Management", + "waf": "Operations" + }, + { + "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": [ + "Entra" + ], + "severity": "Medium", + "subcategory": "Cloud Solution Provider", + "text": "Ensure that Azure Lighthouse is used for administering the tenant by partner", + "waf": "Cost" + }, + { + "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": [ + "Entra" + ], + "severity": "Low", + "subcategory": "Cloud Solution Provider", + "text": "Discuss support request and escalation process with CSP partner", + "waf": "Cost" + }, + { + "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": [ + "Cost", + "Entra" + ], + "severity": "Medium", + "subcategory": "Cloud Solution Provider", + "text": "Setup Cost Reporting and Views with Azure Cost Management", + "waf": "Cost" + }, + { + "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": [ + "Entra", + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": "Enterprise Agreement", + "text": "Configure Notification Contacts to a group mailbox", + "waf": "Cost" + }, + { + "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": [ + "TrafficManager", + "Entra" + ], + "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" + }, + { + "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": [ + "Entra" + ], + "severity": "High", + "subcategory": "Enterprise Agreement", + "text": "Ensure that Accounts are configured to be of the type 'Work or School Account", + "waf": "Security" + }, + { + "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": [ + "Cost", + "Entra" + ], + "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": "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": [ + "Subscriptions", + "Cost", + "Entra" + ], + "severity": "Low", + "subcategory": "Enterprise Agreement", + "text": "Make use of Enterprise Dev/Test Subscriptions to reduce costs for non-production workloads", + "waf": "Cost" + }, + { + "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": [ + "RBAC", + "Entra" + ], + "severity": "Medium", + "subcategory": "Enterprise Agreement", + "text": "Periodically audit the role assignments to review who has access to your Enterprise Agreement Enrollment", + "waf": "Cost" + }, + { + "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": [ + "Entra" + ], + "severity": "Low", + "subcategory": "Microsoft Customer Agreement", + "text": "Configure Agreement billing account notification contact email", + "waf": "Cost" + }, + { + "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", + "Entra" + ], + "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": "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", + "Entra" + ], + "severity": "Low", + "subcategory": "Microsoft Customer Agreement", + "text": "Make use of Azure Plan to reduce costs for non-production workloads", + "waf": "Cost" + }, + { + "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": [ + "RBAC", + "Entra" + ], + "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" + }, + { + "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": [ + "Entra" + ], + "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": "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": [ + "ASR", + "Entra" + ], + "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" + }, + { + "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": [ + "Entra" + ], + "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": "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": [ + "Monitor", + "Entra" + ], + "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" + }, + { + "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": [ + "ACR", + "Subscriptions", + "RBAC", + "Entra" + ], + "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": "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": [ + "AzurePolicy", + "Entra" + ], + "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" + }, + { + "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": [ + "Entra" + ], + "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": "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": [ + "RBAC", + "Entra" + ], + "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": "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": [ + "Entra" + ], + "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" + }, + { + "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": [ + "Entra" + ], + "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": "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": "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": [ + "Subscriptions", + "RBAC", + "Entra" + ], + "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": "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": [ + "Subscriptions", + "Entra" + ], + "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": "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": [ + "Entra" + ], + "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": "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": [ + "Entra" + ], + "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": "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": [ + "VPN", + "Entra" + ], + "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": "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": [ + "RBAC", + "Entra" + ], + "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": "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": [ + "VNet", + "Entra" + ], + "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": "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": [ + "ACR", + "AKV", + "Entra", + "RBAC", + "Storage" + ], + "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": "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": [ + "Entra" + ], + "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" + }, + { + "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": [ + "Subscriptions" + ], + "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": "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": [ + "Subscriptions" + ], + "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": "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": [ + "AzurePolicy", + "Subscriptions", + "RBAC" + ], + "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": "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": [ + "Subscriptions", + "ExpressRoute", + "DNS", + "VWAN" + ], + "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": "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": [ + "Subscriptions" + ], + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Enforce no subscriptions are placed under the root management group", + "waf": "Security" + }, + { + "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": [ + "Subscriptions", + "RBAC" + ], + "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": "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": [ + "Subscriptions" + ], + "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" + }, + { + "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": [ + "AzurePolicy", + "Cost", + "RBAC", + "Subscriptions" + ], + "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": [ + "AzurePolicy", + "Cost", + "Subscriptions", + "VM" + ], + "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": [ + "Subscriptions", + "Monitor" + ], + "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": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "C02.12", + "link": "https://azure.microsoft.com/global-infrastructure/services/", + "services": [ + "Subscriptions" + ], + "severity": "Medium", + "subcategory": "Subscriptions", + "text": "Ensure required services and features are available within the chosen deployment regions", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", + "waf": "Security" + }, + { + "ammp": true, + "category": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "C02.13", + "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", + "services": [ + "Cost", + "Subscriptions" + ], + "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": "Resource Organization", + "checklist": "Azure Landing Zone Review", + "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "C02.14", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "services": [ + "Subscriptions", + "Entra" + ], + "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" + }, + { + "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.15", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", + "services": [ + "Cost", + "Subscriptions" + ], + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "D01.01", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "services": [ + "FrontDoor", + "AKV" + ], + "severity": "Medium", + "subcategory": "App delivery", + "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" + }, + { + "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": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "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": "D01.03", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", + "services": [ + "AppGW" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "Ensure you are using Application Gateway v2 SKU", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "D01.04", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "services": [ + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "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", + "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "D01.05", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", + "services": [ + "AppGW", + "VNet" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "description": "Administration of reverse proxies in general and WAF in particular is closer to the application than to networking, so they belong in the same subscription as the app. Centralizing the Application Gateway and WAF in the connectivity subscription might be OK if it is managed by one single team.", + "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "D01.06", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "Subscriptions", + "Entra", + "WAF", + "AppGW", + "NVA", + "VNet" + ], + "severity": "Medium", + "subcategory": "App delivery", + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "D01.07", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "DDoS" + ], + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "D01.08", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "AzurePolicy", + "FrontDoor", + "WAF" + ], + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "D01.09", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", + "services": [ + "AppGW", + "FrontDoor", + "AzurePolicy", + "WAF" + ], + "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 Landing Zone Review", + "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "D01.10", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", + "services": [ + "TrafficManager" + ], + "severity": "High", + "subcategory": "App delivery", + "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" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "D01.11", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "services": [ + "Entra", + "AVD" + ], + "severity": "Low", + "subcategory": "App delivery", + "text": "If users only need access to internal applications, has Microsoft Entra ID Application Proxy been considered as an alternative to Azure Virtual Desktop (AVD)?", + "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "D01.12", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", + "services": [ + "Entra" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "To reduce the number of firewall ports open for incoming connections in your network, consider using Microsoft Entra ID Application Proxy to give remote users secure and authenticated access to internal applications.", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "waf": "Security" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "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": "D01.13", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", + "services": [ + "FrontDoor", + "Storage", + "WAF" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", + "waf": "Security" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "D01.14", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", + "services": [ + "FrontDoor", + "TrafficManager" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", + "waf": "Security" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "D01.15", + "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", + "text": "Use the same domain name on Azure Front Door and your origin. Mismatched host names can cause subtle bugs.", + "waf": "Security" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "D01.16", + "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", + "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", + "waf": "Performance" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "D01.17", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", + "services": [ + "FrontDoor" + ], + "severity": "Medium", + "subcategory": "App delivery", + "text": "Select good health probe endpoints for Azure Front Door. Consider building health endpoints that check all of your application's dependencies.", + "waf": "Reliability" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "D01.18", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", + "services": [ + "FrontDoor" + ], + "severity": "Low", + "subcategory": "App delivery", + "text": "Use HEAD health probes with Azure Front Door, to reduce the traffic that Front Door sends to your application.", + "waf": "Performance" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "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": "D01.19", + "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", + "services": [ + "LoadBalancer" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", + "waf": "Reliability" + }, + { + "ammp": true, + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "D01.20", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", + "services": [ + "FrontDoor", + "Cost", + "AKV" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Use managed TLS certificates with Azure Front Door. Reduce operational cost and risk of outages due to certificate renewals.", + "waf": "Operations" + }, + { + "category": "Network Topology and Connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "D01.21", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "Medium", + "subcategory": "App delivery", + "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" + }, + { + "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": [ + "ExpressRoute" + ], + "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": "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": [ + "VPN", + "ExpressRoute" + ], + "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": "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": [ + "VNet" + ], + "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" + }, + { + "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": [ + "VPN", + "Entra", + "NVA", + "VNet", + "ExpressRoute", + "Firewall", + "DNS" + ], + "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" + }, + { + "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": [ + "NVA" + ], + "severity": "Medium", + "subcategory": "Hub and spoke", + "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance", + "waf": "Reliability" + }, + { + "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": [ + "VPN", + "ARS", + "ExpressRoute" + ], + "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": "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": [ + "VNet", + "ARS" + ], + "severity": "Low", + "subcategory": "Hub and spoke", + "text": "If using Route Server, use a /27 prefix for the Route Server subnet.", + "waf": "Security" + }, + { + "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": [ + "ACR", + "VNet" + ], + "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": "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": [ + "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": "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": [ + "VNet", + "ExpressRoute", + "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" + }, + { + "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": [ + "Storage" + ], + "severity": "Medium", + "subcategory": "Hub and spoke", + "text": "Consider the limit of routes per route table (400).", + "waf": "Reliability" + }, + { + "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": [ + "VNet" + ], + "severity": "High", + "subcategory": "Hub and spoke", + "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings", + "waf": "Reliability" + }, + { + "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": [ + "ExpressRoute" + ], + "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": "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": [ + "ExpressRoute" + ], + "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": "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": [ + "VPN", + "ExpressRoute" + ], + "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": [ + "Cost", + "ExpressRoute" + ], + "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" + }, + { + "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": [ + "Cost", + "ExpressRoute" + ], + "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": "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": [ + "ExpressRoute" + ], + "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" + }, + { + "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": [ + "ExpressRoute" + ], + "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": "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": [ + "ExpressRoute" + ], + "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" + }, + { + "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" + ], + "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" + }, + { + "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": [ + "Cost", + "ExpressRoute" + ], + "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" + }, + { + "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": [ + "ExpressRoute" + ], + "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" + }, + { + "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": [ + "Monitor", + "ExpressRoute" + ], + "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" + }, + { + "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": [ + "ACR", + "Monitor", + "NetworkWatcher" + ], + "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" + }, + { + "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": [ + "ExpressRoute" + ], + "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" + }, + { + "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": [ + "VM" + ], + "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" + }, + { + "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": [ + "ACR", + "VNet" + ], + "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": "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": [ + "VNet" + ], + "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" + }, + { + "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": [ + "VNet" + ], + "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" + }, + { + "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": [ + "VNet" + ], + "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" + }, + { + "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": [ + "VNet", + "DNS" + ], + "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": "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": [ + "ACR", + "VNet", + "DNS" + ], + "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": "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": [ + "VNet", + "DNS" + ], + "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" + }, + { + "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": [ + "VNet", + "VM", + "DNS" + ], + "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": "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": [ + "Bastion" + ], + "severity": "Medium", + "subcategory": "Internet", + "text": "Consider using Azure Bastion to securely connect to your network.", + "waf": "Security" + }, + { + "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": [ + "VNet", + "Bastion" + ], + "severity": "Medium", + "subcategory": "Internet", + "text": "Use Azure Bastion in a subnet /26 or larger.", + "waf": "Security" + }, + { + "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": [ + "Firewall" + ], + "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": "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": [ + "ACR", + "AzurePolicy", + "RBAC", + "Firewall" + ], + "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" + }, + { + "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": [ + "Firewall" + ], + "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": "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": [ + "ACR", + "FrontDoor", + "AzurePolicy", + "WAF" + ], + "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" + }, + { + "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": [ + "AppGW", + "FrontDoor", + "AzurePolicy", + "WAF" + ], + "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" + }, + { + "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": [ + "VNet", + "WAF" + ], + "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" + }, + { + "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": [ + "VNet", + "DDoS" + ], + "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" + }, + { + "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": [ + "Firewall", + "DNS" + ], + "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" + }, + { + "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": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Use Azure Firewall Premium for additional security and protection.", + "waf": "Security" + }, + { + "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": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection.", + "waf": "Security" + }, + { + "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": [ + "Firewall" + ], + "severity": "High", + "subcategory": "Internet", + "text": "Configure Azure Firewall IDPS mode to Deny for additional protection.", + "waf": "Security" + }, + { + "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": [ + "NVA", + "VWAN", + "VNet", + "Storage", + "Firewall" + ], + "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": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "D07.01", + "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", + "services": [ + "VNet" + ], + "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": "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": [ + "PrivateLink" + ], + "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": "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": [ + "PrivateLink", + "ExpressRoute" + ], + "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": "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": [ + "VNet" + ], + "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" + }, + { + "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": [ + "Firewall", + "PrivateLink", + "NVA", + "DNS" + ], + "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" + }, + { + "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": [ + "VNet", + "Firewall" + ], + "severity": "High", + "subcategory": "Segmentation", + "text": "Use a /26 prefix for your Azure Firewall subnets.", + "waf": "Security" + }, + { + "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": [ + "VNet", + "VPN", + "ExpressRoute" + ], + "severity": "High", + "subcategory": "Segmentation", + "text": "Use at least a /27 prefix for your Gateway subnets", + "waf": "Security" + }, + { + "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": [ + "VNet" + ], + "severity": "Medium", + "subcategory": "Segmentation", + "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity.", + "waf": "Security" + }, + { + "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": [ + "VNet" + ], + "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": [ + "ACR", + "VNet" + ], + "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": "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": [ + "VNet", + "VM" + ], + "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" + }, + { + "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": [ + "VNet", + "NetworkWatcher" + ], + "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" + }, + { + "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": [ + "VWAN" + ], + "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" + }, + { + "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": [ + "ACR", + "VWAN" + ], + "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": "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": [ + "ACR", + "VWAN" + ], + "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": "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": [ + "VWAN", + "Firewall" + ], + "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": "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": [ + "VWAN" + ], + "severity": "Medium", + "subcategory": "Virtual WAN", + "text": "Ensure that the network architecture is within the Azure Virtual WAN limits.", + "waf": "Reliability" + }, + { + "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": [ + "Monitor", + "VWAN" + ], "severity": "Medium", - "subcategory": "Privileged administration", - "text": "Ensure critical impact admins use a workstation with elevated security protections and monitoring" + "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": "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", - "severity": "High", - "subcategory": "External Identities", - "text": "Identity Providers: Verify external identity providers are known" + "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": [ + "VWAN" + ], + "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" }, { - "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", - "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Guest user access set to 'Guest user access is restricted?'" + "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": [ + "VPN", + "VWAN", + "ExpressRoute" + ], + "severity": "Medium", + "subcategory": "Virtual WAN", + "text": "Use AS-Path as hub routing preference, since it is more flexible than ExpressRoute or VPN.", + "waf": "Reliability" }, { - "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", - "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Guest invite settings set to 'Only users assigned to specific admin roles'" + "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": [ + "VWAN" + ], + "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": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "909aed8c-44cf-43b2-a381-8bafa2cf2149", - "link": "https://learn.microsoft.com/azure/active-directory/external-identities/delegate-invitations", + "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": [ + "VWAN" + ], "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Enable guest self-service sign up via flows set to 'Disabled' " + "subcategory": "Virtual WAN", + "text": "Assign enough IP space to virtual hubs, ideally a /23 prefix.", + "waf": "Reliability" }, { - "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", + "ammp": true, + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "D10.01", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", + "services": [ + "FrontDoor" + ], "severity": "High", - "subcategory": "External Identities", - "text": "External Collaboration Settings: Collaboration restrictions set to 'Allow invitations to the specified domains'" + "subcategory": "App delivery", + "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" }, { - "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": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "D10.02", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", + "services": [ + "FrontDoor" + ], "severity": "Medium", - "subcategory": "External Identities", - "text": "Access Reviews: Enabled for all groups" + "subcategory": "App delivery", + "text": "Use HTTP to HTTPS redirection with Azure Front Door. Support older clients by redirecting them to an HTTPS request automatically.", + "waf": "Security" }, { - "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", - "severity": "Medium", - "subcategory": "Enterprise Applications", - "text": "Consent & Permissions: Allow user consent for apps from verified publishers" + "ammp": true, + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "D10.03", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", + "waf": "Security" }, { - "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", - "severity": "Medium", - "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": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "D10.04", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", + "waf": "Security" }, { - "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", + "ammp": true, + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "D10.05", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Custom Domains", - "text": "Only validated customer domains are registered" + "subcategory": "App delivery", + "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", + "waf": "Security" }, { - "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", + "ammp": true, + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "D10.06", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Password Reset", - "text": "Self-service password reset policy requirement verified compliant." + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", + "waf": "Security" }, { - "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", + "ammp": true, + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "D10.07", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "High", + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", + "waf": "Security" + }, + { + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "D10.08", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", + "services": [ + "FrontDoor", + "WAF" + ], "severity": "Medium", - "subcategory": "Password Reset", - "text": "Set number of days before users are asked to re-confirm authentication information is not set to zero" + "subcategory": "App delivery", + "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" }, { - "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", - "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": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "D10.09", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "Medium", + "subcategory": "App delivery", + "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" }, { - "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", - "severity": "High", - "subcategory": "User Setting", - "text": "Disable 'Users can register applications'" + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "D10.10", + "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" + ], + "severity": "Medium", + "subcategory": "App delivery", + "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" }, { - "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", - "severity": "High", - "subcategory": "User Setting", - "text": "Restrict access to Administrative portal (portal.azure.com) to administrators only" + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "D10.11", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "Low", + "subcategory": "App delivery", + "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" }, { - "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", - "severity": "High", - "subcategory": "User Setting", - "text": "Disable 'LinkedIn account connection'" + "category": "Network topology and connectivity", + "checklist": "Azure Landing Zone Review", + "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "D10.12", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", + "services": [ + "FrontDoor", + "WAF" + ], + "severity": "Medium", + "subcategory": "App delivery", + "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": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "7fb012f7-0943-4f63-8472-2ea39d2b1ce6", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-monitoring", + "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": [ + "AzurePolicy" + ], "severity": "High", - "subcategory": "Diagnostic Settings", - "text": "Enabled and send to Log Analytics workspace with Sentinel" + "subcategory": "Governance", + "text": "Leverage Azure Policy strategically, define controls for your environment, using Policy Initiatives to group related policies.", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "PIM enabled", - "text": "Privileged Identity Management enabled" + "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": [ + "AzurePolicy" + ], + "severity": "Medium", + "subcategory": "Governance", + "text": "Identify required Azure tags and use the 'append' policy mode to enforce usage via Azure Policy.", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "PIM enabled", - "text": "Implement 'just in time' (JIT) access to further lower the exposure time for privileged accounts (reduce standing access)" + "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": [ + "AzurePolicy", + "RBAC" + ], + "severity": "Medium", + "subcategory": "Governance", + "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments.", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Configure conditional access policies / Access Controls" + "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": [ + "AzurePolicy", + "Subscriptions" + ], + "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": "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": "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": [ + "AzurePolicy" + ], "severity": "Medium", - "subcategory": "Conditional Access Policies", - "text": "Conditions: Restricted Locations" + "subcategory": "Governance", + "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required.", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: MFA enabled for all users" + "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": [ + "AzurePolicy", + "Subscriptions" + ], + "severity": "Low", + "subcategory": "Governance", + "text": "Use Azure Policy to control which services users can provision at the subscription/management group level", + "waf": "Security" }, { - "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": "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": [ + "AzurePolicy" + ], "severity": "Medium", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Require MFA for Administrators" + "subcategory": "Governance", + "text": "Use built-in policies where possible to minimize operational overhead.", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Require MFA for Azure Management " + "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": [ + "AzurePolicy", + "Subscriptions", + "RBAC", + "Entra" + ], + "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": "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", - "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Block Legacy Protocols" + "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": [ + "AzurePolicy", + "Subscriptions" + ], + "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" }, { - "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", - "severity": "High", - "subcategory": "Conditional Access Policies", - "text": "Access Controls: Require devices to be marked as compliant" + "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": [ + "AzurePolicy" + ], + "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" }, { - "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/", - "severity": "Medium", - "subcategory": "Guest users", - "text": "Is there a policy to track guest user accounts (i.e. usage/delete/disable)?" + "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": [ + "Cost", + "TrafficManager", + "VM" + ], + "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": "Identity", - "checklist": "Azure Security Review Checklist", - "guid": "c5bb4e4f-1814-4287-b5ca-8c26c9b32ab5", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/identity-secure-score", - "severity": "High", - "subcategory": "Identity Secure Score", - "text": "Implement Identity Secure Score based on best practices in your industry" + "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": [ + "VM" + ], + "severity": "Medium", + "subcategory": "Scalability", + "text": "Leverage Azure Virtual Machine Scale sets to scale in and out based on the load.", + "waf": "Reliability" }, { - "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", + "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": [ + "Cost", + "Monitor", + "TrafficManager" + ], "severity": "Medium", - "subcategory": "Break Glass Accounts", - "text": "At least two break glass accounts have been created and policy around their use exists" + "subcategory": "Optimize your cloud investment", + "text": "Configure 'Actual' and 'Forecasted' Budget Alerts.", + "waf": "Cost" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "0ac252b9-99a6-48af-a7c9-a8f821b8eb8c", - "link": "https://learn.microsoft.com/azure/governance/policy/overview", + "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": [ + "FrontDoor", + "WAF" + ], "severity": "High", - "subcategory": "Access Control", - "text": "Control VM Access leveraging Azure Policy" + "subcategory": "App delivery", + "text": "Add diagnostic settings to save your Azure Front Door WAF's logs. Regularly review the logs to check for attacks and for false positive detections.", + "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": "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", + "services": [ + "FrontDoor", + "Sentinel" + ], "severity": "Medium", - "subcategory": "Access Control", - "text": "Reduce variability in your setup and deployment of VMs by leveraging templates" + "subcategory": "App delivery", + "text": "Send Azure Front Door logs to Microsoft Sentinel. Detect attacks and integrate Front Door telemetry into your overall Azure environment.", + "waf": "Operations" }, { - "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": "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": [], "severity": "Medium", - "subcategory": "Access Control", - "text": "Secure privileged access to deploy VMS by reducing who has access to Resources through Governance" + "subcategory": "Data Protection", + "text": "Consider cross-region replication in Azure for BCDR with paired regions", + "waf": "Reliability" }, { - "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": "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", + "services": [ + "Backup" + ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Use multiple VMs for your workloads for better availability " + "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": "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": "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", + "services": [ + "AzurePolicy", + "Monitor", + "RBAC", + "Entra" + ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Deploy and test a disaster recovery solution " + "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": "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", + "checklist": "Azure Landing Zone Review", + "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "F03.02", + "services": [ + "Monitor" + ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Availability sets" + "subcategory": "Monitoring", + "text": "Is the landing zone documented?", + "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", + "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": [ + "Monitor", + "ARS" + ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Availability Zones" + "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": "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", + "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": [ + "AzurePolicy", + "Monitor" + ], "severity": "Medium", - "subcategory": "High Availability ", - "text": "Regional fault tolerance " - }, - { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "af225ca4-4e16-496f-bdde-ace4cb1deb4c", - "link": "https://learn.microsoft.com/azure/security/fundamentals/antimalware", - "severity": "High", - "subcategory": "Protect against malware", - "text": "Install antimalware solutions" + "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": "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", - "severity": "High", - "subcategory": "Protect against malware", - "text": "Integrate antimalware solution with Security Center" + "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", + "services": [ + "AzurePolicy", + "Monitor", + "VM" + ], + "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" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "7a0177a2-b594-45bd-a433-34fdf91c2341", + "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", - "severity": "High", - "subcategory": "Manage VM Updates", - "text": "Keep VMs up to date using Update Management with Azure Automation" + "services": [ + "Monitor", + "VM" + ], + "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" }, { - "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", + "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": [ + "Monitor", + "NetworkWatcher" + ], "severity": "Medium", - "subcategory": "Manage VM Updates", - "text": "Ensure Windows images for deployment have the most recent level of updates " + "subcategory": "Monitoring", + "text": "Use Network Watcher to proactively monitor traffic flows", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "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", - "severity": "High", - "subcategory": "Manage VM Updates", - "text": "Rapidly apply security updates to VMs using Microsoft Defender for Cloud" + "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": [ + "Monitor" + ], + "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" }, { - "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", - "severity": "High", - "subcategory": "Encrypt your VHDs", - "text": "Enable encryption on your VMs" + "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", + "Monitor", + "RBAC" + ], + "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": "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", - "severity": "High", - "subcategory": "Encrypt your VHDs", - "text": "Add Key Encryption Key (KEK) for added layer of security for encryption " + "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": "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": "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", + "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": [ + "Monitor" + ], "severity": "Medium", - "subcategory": "Encrypt your VHDs", - "text": "Take a snapshot of disks before encryption for rollback purposes" + "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": "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", - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Ensure only the central networking group has permissions to networking resources " + "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" + ], + "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" }, { - "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", - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Identity and remediate exposed VMs that allow access from 'ANY' source IP address" + "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", + "RBAC", + "Entra" + ], + "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" }, { - "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", - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Restrict management ports (RDP, SSH) using Just-in-Time Access" + "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" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Monitor Logs for insights and reporting.", + "waf": "Operations" }, { - "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", - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Remove internet access and implement jump servers for RDP" + "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": [ + "Storage", + "Monitor" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage.", + "waf": "Operations" }, { - "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", - "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": "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": [ + "Monitor" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Use Azure Monitor alerts for the generation of operational alerts.", + "waf": "Operations" }, { - "category": "VM Security Checks", - "checklist": "Azure Security Review Checklist", - "guid": "dad6aae1-1e6b-484e-b5df-47d2d92881b1", - "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", - "severity": "High", - "subcategory": "Restrict direct internet connection ", - "text": "Leverage Azure Bastion as your RDP/SSH broker for added security and reduction in footprint" + "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": [ + "Monitor" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied", + "waf": "Operations" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "cd5d1e54-a297-459e-9968-0e78289c9356", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", - "severity": "High", - "subcategory": "Architecture ", - "text": "All tenants contain have Sentinel enabled on at least one Log Analytics workspace" + "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": [ + "Monitor" + ], + "severity": "Medium", + "subcategory": "Monitoring", + "text": "Consider supported regions for linked Log Analytics workspace and automation accounts", + "waf": "Operations" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "57d02bff-4564-4b0d-a34a-359836ee79d6", - "link": "https://learn.microsoft.com/azure/sentinel/best-practices-workspace-architecture", - "severity": "High", - "subcategory": "Architecture ", - "text": "Customer understands Sentinel architecture" + "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": [ + "AzurePolicy", + "VM" + ], + "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" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "e8f5c586-c7d9-4cdc-86ac-c075ef9b141a", - "link": "https://learn.microsoft.com/azure/sentinel/multiple-workspace-view", + "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": [ + "AzurePolicy", + "Monitor", + "VM" + ], "severity": "Medium", - "subcategory": "Architecture ", - "text": "Customer knows how to monitor Incidents across multiple Sentinel instances" + "subcategory": "Operational compliance", + "text": "Monitor VM security configuration drift via Azure Policy.", + "waf": "Security" }, { - "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": "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": [ + "ACR", + "ASR", + "VM" + ], "severity": "Medium", - "subcategory": "Overview", - "text": "No Incidents open more than 24 hours" + "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": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "5d3c4ada-97cb-43d1-925a-b225c6f4e068", - "link": "https://learn.microsoft.com/azure/sentinel/whats-new", - "severity": "Low", - "subcategory": "News & Guides", - "text": "Customer have been shown the News & Guides tab" + "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": [ + "ASR" + ], + "severity": "Medium", + "subcategory": "Protect and Recover", + "text": "Ensure to use and test native PaaS service disaster recovery capabilities.", + "waf": "Operations" }, { - "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": "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": [ + "Backup" + ], "severity": "Medium", - "subcategory": "UEBA ", - "text": "UEBA Configured (Sentinel/Settings/Settings/Configure UEBA)" + "subcategory": "Protect and Recover", + "text": "Use Azure-native backup capabilities, or an Azure-compatible, 3rd-party backup solution.", + "waf": "Operations" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "e69d8d9a-3eec-4218-b687-ab077adb49e5", - "link": "https://learn.microsoft.com/azure/sentinel/connect-azure-active-directory", + "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": [ + "VM" + ], "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Active Directory in configured and 'Last Log Received' shows today" + "subcategory": "Fault Tolerance", + "text": "Leverage Availability Zones for your VMs in regions where they are supported.", + "waf": "Reliability" }, { - "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", + "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": [ + "VM" + ], "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Active Directory Identity Protection is configured and 'Last Log Received' shows today" + "subcategory": "Fault Tolerance", + "text": "Avoid running a production workload on a single VM.", + "waf": "Reliability" }, { - "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", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Activity is configured is configured and 'Last Log Received' shows today" + "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": [ + "AppGW", + "ACR", + "LoadBalancer" + ], + "severity": "Medium", + "subcategory": "Fault Tolerance", + "text": "Azure Load Balancer and Application Gateway distribute incoming network traffic across multiple resources.", + "waf": "Reliability" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "8e13f9cc-bd46-4826-9abc-a264f9a19bfe", - "link": "https://learn.microsoft.com/azure/sentinel/connect-defender-for-cloud", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Microsoft Defender for Cloud is configured and 'Last Log Received' shows today" + "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" }, { - "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", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Azure Firewall is configured and 'Last Log Received' shows today" + "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": [], + "severity": "Medium", + "subcategory": "Access control", + "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate.", + "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", + "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", + "services": [ + "AKV" + ], "severity": "High", - "subcategory": "Data Connectors", - "text": "Windows Firewall is configured and 'Last Log Received' shows today" + "subcategory": "Encryption and keys", + "text": "Use Azure Key Vault to store your secrets and credentials", + "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", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Security Events is configured with AMA and 'Last Log Received' shows today" + "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", + "services": [ + "AKV" + ], + "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" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "1a4834ac-9322-423e-ae80-b123081a5417", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Security Events - verify Azure computers are connected and sending data to the workspace" + "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", + "services": [ + "AzurePolicy", + "AKV" + ], + "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": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "859c773e-7e26-4162-9b77-5a917e1f348e", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Security Events - verify non-Azure computers are connected and sending data to the workspace" + "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", + "services": [ + "RBAC", + "Entra", + "AKV" + ], + "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 Landing Zone Review", + "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "G02.05", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AKV" + ], + "severity": "Medium", + "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 Landing Zone Review", + "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "G02.06", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", + "services": [ + "AKV" + ], + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Establish an automated process for key and certificate rotation.", + "waf": "Security" }, { - "category": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "f354c27d-42e8-4bba-a868-155abb9163e9", - "link": "https://learn.microsoft.com/azure/sentinel/connect-aws?tabs=s3", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Connector for AWS" + "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", + "services": [ + "VNet", + "PrivateLink", + "AKV" + ], + "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": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "909ae28c-84c3-43b6-a780-8bafe6c42149", - "link": "https://learn.microsoft.com/azure/sentinel/data-connectors-reference", - "severity": "High", - "subcategory": "Data Connectors", - "text": "Connector for GCP" + "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", + "services": [ + "Monitor", + "Entra", + "AKV" + ], + "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": "Sentinel", - "checklist": "Azure Security Review Checklist", - "guid": "d413a923-c357-44d1-8028-ac6aae01e6a8", - "link": "https://learn.microsoft.com/azure/sentinel/detect-threats-built-in", - "severity": "High", - "subcategory": "Analytics Rules", - "text": "Customer has enabled Analytics rules and configured Incidents " + "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", + "services": [ + "AzurePolicy", + "AKV" + ], + "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": "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/", + "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", + "services": [ + "AKV" + ], "severity": "Medium", - "subcategory": "Settings", - "text": "Customer does not have a daily cap enabled" + "subcategory": "Encryption and keys", + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required.", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "9e3558fd-7724-49c9-9111-2d027fe412f7", - "link": "https://learn.microsoft.com/azure/firewall/premium-features", - "severity": "High", - "subcategory": "Configuration", - "text": "Azure Firewall Premium deployed" + "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" + ], + "severity": "Medium", + "subcategory": "Encryption and keys", + "text": "Use an Azure Key Vault per application per environment per region.", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "Configuration", - "text": "Quad zero/force tunning enabled through Azure Firewall" + "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", + "services": [ + "ACR", + "ASR", + "AKV" + ], + "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" }, { - "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", + "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", + "services": [ + "Entra" + ], "severity": "Medium", - "subcategory": "Access Control", - "text": "RBAC set to enable only authorized users" + "subcategory": "Operations", + "text": "Use Microsoft Entra ID reporting capabilities to generate access control audit reports.", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "8093dc9f-c9d1-4bb7-9b36-a5a67fbb9ed5", - "link": "https://learn.microsoft.com/azure/firewall/firewall-diagnostics", + "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", + "services": [ + "Storage", + "ARS", + "Monitor" + ], "severity": "Medium", - "subcategory": "Diagnostic Settings", - "text": "Diagnostics enabled and sending metrics to a Log Analytics workspace " + "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" }, { - "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", + "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": [ + "Subscriptions", + "Defender" + ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Hubs and virtual networks are protected or connected through Firewall Premium" + "subcategory": "Operations", + "text": "Enable Defender Cloud Security Posture Management for all subscriptions.", + "waf": "Security" }, { - "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", + "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", + "services": [ + "Subscriptions", + "Defender" + ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Access controls are configured (RBAC)" + "subcategory": "Operations", + "text": "Enable a Defender Cloud Workload Protection Plan for Servers on all subscriptions.", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "5c3a87af-4a79-41f8-a39b-da47768e14c1", - "link": "https://learn.microsoft.com/azure/firewall-manager/policy-overview", + "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", + "services": [ + "Subscriptions", + "Defender" + ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Parent policy is configured " + "subcategory": "Operations", + "text": "Enable Defender Cloud Workload Protection Plans for Azure Resources on all subscriptions.", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "15675c1e-a55b-446a-a48f-f8ae7d7e4b47", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", + "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": "Firewall Manager", - "text": "Policy: Rule collections are defined" + "subcategory": "Operations", + "text": "Enable Endpoint Protection on IaaS Servers.", + "waf": "Security" }, { - "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": "Azure Landing Zone Review", + "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "G03.07", + "link": "https://learn.microsoft.com/azure/security-center/", + "services": [ + "Defender", + "Monitor" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud.", + "waf": "Security" + }, + { + "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", + "services": [ + "Monitor", + "Entra" + ], + "severity": "Medium", + "subcategory": "Operations", + "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace.", + "waf": "Security" + }, + { + "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", + "services": [ + "Storage" + ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: DNAT policies are defined" + "subcategory": "Overview", + "text": "Secure transfer to storage accounts should be enabled", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "d66a786d-60e9-46c9-9ad8-855d04c2b39c", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", + "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", + "services": [ + "Storage" + ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Network rules are defined" + "subcategory": "Overview", + "text": "Enable container soft delete for the storage account to recover a deleted container and its contents.", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "986bb2c1-2149-4a11-9b5e-3df574ecccd9", - "link": "https://learn.microsoft.com/azure/firewall/features", + "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", + "services": [ + "Entra" + ], "severity": "High", - "subcategory": "Firewall Manager", - "text": "Policy: Application rules are defined" + "subcategory": "Secure privileged access", + "text": "Separate privileged admin accounts for Azure administrative tasks.", + "waf": "Security" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "793a6bcd-a3b5-40eb-8eb0-3dd95d58d7c8", - "link": "https://learn.microsoft.com/azure/firewall/dns-details", + "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": [], "severity": "Medium", - "subcategory": "Firewall Manager", - "text": "DNS: Feature understood and applied or not applied" + "subcategory": "Service enablement framework", + "text": "Plan how new azure services will be implemented", + "waf": "Security" }, { - "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", - "severity": "High", - "subcategory": "Firewall Manager", - "text": "Threat Intelligence: Set to Alert & Deny" + "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" }, { - "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", + "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": "Firewall Manager", - "text": "Threat Intelligence: Allowed list (justify if they are being used - ie performance)" + "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": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "623b365a-917e-4cbe-98eb-d54cd7df2e8b", - "link": "https://learn.microsoft.com/azure/firewall/premium-certificates", - "severity": "High", - "subcategory": "Firewall Manager", - "text": "TLS enabled" + "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": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "bac35715-59ab-4915-9e99-08aed8c44ce3", - "link": "https://learn.microsoft.com/azure/firewall/rule-processing", - "severity": "High", - "subcategory": "Firewall Manager", - "text": "IDPS enabled" + "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" }, { - "category": "Azure Firewall", - "checklist": "Azure Security Review Checklist", - "guid": "b2b3808b-9fa1-4cf1-849d-003a923ce474", - "link": "https://learn.microsoft.com/azure/firewall/snat-private-range", + "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": "Firewall Manager", - "text": "SNAT: Configured " - }, - { - "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", - "severity": "Medium", - "subcategory": "DDOS Protection", - "text": "Enabled for Firewall public IP's" + "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": "BCDR", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Ensure that your backups are protected against attacks. This should include encryption of the backups to protect against loss of confidentiality. For regular Azure service backup, backup data is automatically encrypted using Azure platform-managed keys. You can also choose to encrypt the backup using a customer-managed key. In this case, ensure this customer-managed key in the key vault is also in the backup scope.", - "guid": "676f6951-0368-49e9-808d-c33a692c9a64", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-2-encrypt-backup-data", + "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": "Azure Key Vault", - "text": "Protect your backup data with encryption and store keys safely in Azure Key Vault" + "subcategory": "DevOps Team Topologies", + "text": "Include unit tests for IaC and application code as part of your build process.", + "waf": "Operations" }, { - "category": "BCDR", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Azure SQL Database uses SQL Server technology to create full backups every week, differential backup every 12-24 hours, and transaction log backup every 5 to 10 minutes. By default, SQL Database stores data in geo-redundant storage blobs that are replicated to a paired region.", - "guid": "e2518261-b3bc-4bd1-b331-637fb2df833f", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#br-1-ensure-regular-automated-backups", - "severity": "Medium", - "subcategory": "Backup", - "text": "Configure Azure SQL Database automated backups" + "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": "BCDR", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "By default, SQL Database stores data in geo-redundant storage blobs that are replicated to a paired region. For SQL Database, the backup storage redundancy can be configured at the time of database creation or can be updated for an existing database; the changes made to an existing database apply to future backups only.", - "guid": "f8c7cda2-3ed7-43fb-a100-85dcd12a0ee4", - "link": "https://learn.microsoft.com/azure/azure-sql/database/automated-backups-overview?tabs=single-database&view=azuresql#backup-storage-redundancy", + "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": "Backup", - "text": "Enable geo-redundant backup storage to protect against single region failure and data loss" + "subcategory": "DevOps Team Topologies", + "text": "Implement automation for File > New > Landing Zone for applications and workloads.", + "waf": "Operations" }, { - "category": "Code", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Malicious code can potentially circumvent security controls. Before deploying custom code to production, it is essential to review what's being deployed. Use a database tool like Azure Data Studio that supports source control. Implement tools and logic for code analysis, vulnerability and credential scanning.", - "guid": "7ca9f006-d2a9-4652-951c-de8e4ac5e76e", - "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-create-server", - "severity": "Medium", - "subcategory": "Source Control and Code Review", - "text": "Use Source Control systems to store, maintain and review application code deployed inside Azure SQLDB Database" + "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": "Data Discovery and Classification", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "In case of classification requirements Purview is the preferred option. Only use SQL Data Discovery & Classification in case Purview is not an option. Discover columns that potentially contain sensitive data. What is considered sensitive data heavily depends on the customer, compliance regulation, etc., and needs to be evaluated by the users in charge of that data. Classify the columns to use advanced sensitivity-based auditing and protection scenarios. Review results of automated discovery and finalize the classification if necessary.", - "guid": "d401509b-2629-4484-9a7f-af0d29a7778f", - "link": "https://learn.microsoft.com/azure/azure-sql/database/data-discovery-and-classification-overview?view=azuresql#faq---advanced-classification-capabilities", + "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": "Data Discovery and Classification", - "text": "Plan and configure Data Discovery & Classification to protect the sensitive data" + "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": "Data Masking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Usage of this feature is recommended only if column encryption is not an option and there is a specific requirement to preserve data types and formats. Dynamic data masking limits sensitive data exposure by masking it to non-privileged users. Dynamic data masking helps prevent unauthorized access to sensitive data by enabling customers to designate how much of the sensitive data to reveal with minimal impact on the application layer.", - "guid": "9391fd50-135e-453e-90a7-c1a23f88cc13", - "link": "https://learn.microsoft.com/azure/azure-sql/database/dynamic-data-masking-overview", - "severity": "Low", - "subcategory": "Data Masking", - "text": "Use Data Masking to prevent unauthorized non-admin users data access if no encryption is possible" + "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" }, { - "category": "Defender", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "SQL Advanced Threat Detection (ATP) provides a layer of security that detects potential vulnerabilities and anomalous activity in databases such as SQL injection attacks and unusual behavior patterns. When a potential threat is detected Threat Detection sends an actionable real-time alert by email and in Microsoft Defender for Cloud, which includes clear investigation and remediation steps for the specific threat.", - "guid": "4e52d73f-5d37-428f-b3a2-e6997e835979", - "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-configure", + "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": "Advanced Threat Protection", - "text": "Review and complete Advanced Threat Protection (ATP) configuration" + "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" }, { - "category": "Defender", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Enable Microsoft Defender for Azure SQL at the subscription level to automatically onboard and protect all existing and future servers and databases. When you enable on the subscription level, all databases in Azure SQL Database and Azure SQL Managed Instance are protected. You can then disable them individually if you choose. If you want to manually manage which databases are protected, disable at the subscription level and enable each database that you want protected.", - "guid": "dff87489-9edb-4cef-bdda-86e8212b2aa1", - "link": "https://learn.microsoft.com/azure/azure-sql/database/azure-defender-for-sql?view=azuresql#enable-microsoft-defender-for-sql ", + "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": "Defender for Azure SQL", - "text": "Enable Microsoft Defender for Azure SQL" + "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": "Defender", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Microsoft Defender for Azure SQL ATP detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases. Alerts can be configured and generated and will be reported in the Defender for console.", - "guid": "ca342fdf-d25a-4427-b105-fcd50ff8a0ea", - "link": "https://learn.microsoft.com/azure/azure-sql/database/threat-detection-configure", + "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" + ], "severity": "High", - "subcategory": "Defender for Azure SQL", - "text": "Prepare a security response plan to promptly react to Microsoft Defender for Azure SQL alerts" + "subcategory": "Identity", + "text": "Create a service principal and its role assignments before creating the ARO clusters.", + "waf": "Security" }, { - "category": "Defender", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Azure SQLDB vulnerability assessment is a service that provides visibility into your security state. Vulnerability assessment includes actionable steps to resolve security issues and enhance your database security. It can help you to monitor a dynamic database environment where changes are difficult to track and improve your SQL security posture.", - "guid": "a6101ae7-534c-45ab-86fd-b34c55ea21ca", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/sql-azure-vulnerability-assessment-overview", + "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" + ], "severity": "High", - "subcategory": "Vulnerability Assessment", - "text": "Configure Vulnerability Assessment (VA) findings and review recommendations" + "subcategory": "Identity", + "text": "Use AAD to authenticate users in your ARO cluster.", + "waf": "Security" }, { - "category": "Defender", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Microsoft Defender for Cloud provides vulnerability assessment for your Azure SQL Databases. Vulnerability assessment scans your databases for software vulnerabilities and provides a list of findings. You can use the findings to remediate software vulnerabilities and disable findings.", - "guid": "c8c5f112-1e50-4f77-9264-8195b4cd61ac", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/sql-azure-vulnerability-assessment-find?view=azuresql", + "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", + "services": [ + "RBAC", + "Entra" + ], "severity": "High", - "subcategory": "Vulnerability Assessment", - "text": "Regularly review of Vulnerability Assessment (VA) findings and recommendations and prepare a plan to fix" + "subcategory": "Identity", + "text": "Define OpenShift projects to restrict RBAC privilege and isolate workloads in your cluster.", + "waf": "Security" }, { - "category": "Encryption", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Always Encrypted with Secure Enclaves expands confidential computing capabilities of Always Encrypted by enabling in-place encryption and richer confidential queries. Always Encrypted with Secure Enclaves addresses these limitations by allowing some computations on plaintext data inside a secure enclave on the server side. Usage of this feature is recommended for the cases where you need to limit administrator access and need your queries to support more than equality matching of encrypted columns.", - "guid": "65d7e54a-10a6-4094-b673-9ff3809c9277", - "link": "https://learn.microsoft.com/sql/relational-databases/security/encryption/always-encrypted-enclaves", + "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", + "services": [ + "RBAC", + "Entra" + ], "severity": "Medium", - "subcategory": "Always Encrypted", - "text": "If protecting sensitive PII data from admin users is a key requirement, but Column Encryption limitations cannot be tolerated, consider the adoption of Always Encrypted with Secure Enclaves" + "subcategory": "Identity", + "text": "Define the required RBAC roles in OpenShift are scoped to either a project or a cluster.", + "waf": "Security" }, { - "category": "Encryption", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "With Azure SQL Database, you can apply symmetric encryption to a column of data by using Transact-SQL. This approach is called column encryption, because you can use it to encrypt specific columns with different encryption keys. Doing so gives you more granular encryption capability than TDE, which encrypts data in pages. Using Always Encrypted to ensure sensitive data isn't exposed in plaintext in Azure SQL Database or SQL Managed Instance, even in memory/in use. Always Encrypted protects the data from Database Administrators (DBAs) and cloud admins (or bad actors who can impersonate high-privileged but unauthorized users) and gives you more control over who can access your data.", - "guid": "c03ce136-e3d5-4e17-bf25-ed955ee480d3", - "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#control-access-of-application-users-to-sensitive-data-through-encryption", + "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", + "services": [ + "Entra", + "AKV" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "Minimize the number of users who have administrator rights and secrets access.", + "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", + "services": [ + "RBAC", + "Entra" + ], + "severity": "Medium", + "subcategory": "Identity", + "text": "Use Privileged Identity Management in AAD for ARO users with privileged roles.", + "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", + "services": [ + "Subscriptions", + "Entra", + "WAF", + "DDoS", + "VNet", + "Firewall" + ], "severity": "Low", - "subcategory": "Column Encryption", - "text": "To protect sensitive PII data from non-admin users in specific table columns, consider using Column Encryption" + "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": "Encryption", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Enabled by default, Transparent data encryption (TDE) helps to protect the database files against information disclosure by performing real-time encryption and decryption of the database, associated backups, and transaction log files 'at rest', without requiring changes to the application.", - "guid": "c614ac47-bebf-4061-b0a1-43e0c6b5e00d", - "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-create-server", + "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": "Transparent Data Encryption", - "text": "Ensure Transparent Data Encryption (TDE) is kept enabled" + "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": "Encryption", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "If separation of duties in the management of keys and data within the organization is required, leverage Customer Managed Keys (CMK) for Transparent Data Encryption (TDE) for your Azure SQLDB and use Azure Key Vault to store (refer to its checklist). Leverage this feature when you have strict security requirements which cannot be met by the managed service keys.", - "guid": "2edb4165-4f54-47cc-a891-5c82c2f21e25", - "link": "https://learn.microsoft.com/azure/azure-sql/database/transparent-data-encryption-byok-overview", + "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": [ + "FrontDoor", + "WAF" + ], "severity": "Medium", - "subcategory": "Transparent Data Encryption", - "text": "Use customer-managed keys (CMK) in Azure Key Vault (AKV) if you need increased transparency and granular control over the TDE protection" + "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": "Encryption", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The minimal Transport Layer Security (TLS) version setting allows customers to choose which version of TLS their SQL database uses. It's possible to change the minimum TLS version by using the Azure portal, Azure PowerShell, and the Azure CLI.", - "guid": "7754b605-57fd-4bcb-8213-52c39d8e8225", - "link": "https://learn.microsoft.com/azure/azure-sql/database/connectivity-settings?source=recommendations&view=azuresql&tabs=azure-portal#minimal-tls-version", - "severity": "High", - "subcategory": "Transport Layer Security", - "text": "Enforce minimum TLS version to the latest available" + "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": [ + "FrontDoor", + "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.", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Use Azure Active Directory (Azure AD) authentication for centralized identity management. Use SQL Authentication only if really necessary and document as exceptions.", - "guid": "c9b8b6bf-2c6b-453d-b400-de9a43a549d7", - "link": "https://learn.microsoft.com/azure/azure-sql/database/authentication-aad-overview", + "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": [ + "AzurePolicy", + "NVA", + "Firewall" + ], "severity": "Medium", - "subcategory": "Azure Active Directory", - "text": "Leverage Azure AD authentication for connections to Azure SQL Databases" + "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": "Identity", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Using Azure AD groups simplifies permission management and both the group owner, and the resource owner can add/remove members to/from the group. Create a separate group for Azure AD administrators for each logical server. Monitor Azure AD group membership changes using Azure AD audit activity reports.", - "guid": "29820254-1d14-4778-ae90-ff4aeba504a3", - "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#central-management-for-identities", + "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": [ + "AzurePolicy" + ], + "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": "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": [ + "ACR", + "PrivateLink" + ], "severity": "Medium", - "subcategory": "Azure Active Directory", - "text": "Create a separate Azure AD group with two admin accounts for each Azure SQL Database logical server" + "subcategory": "Private access", + "text": "Use Azure Private Link to secure network connections to managed Azure services, including to Azure Container Registry.", + "waf": "Security" }, { - "category": "Identity", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Ensure that distinct system and user assigned managed identities, that are dedicated to the function, with least permissions assigned, are used for communication from Azure services and applications to the Azure SQLDB databases.", - "guid": "df3a09ee-03bb-4198-8637-d141acf5f289", - "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#minimize-the-use-of-password-based-authentication-for-applications", + "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" + ], + "severity": "High", + "subcategory": "Operations", + "text": "Establish a monitoring process using the inbuilt Prometheus, OpenShift Logging or Container Insights integration.", + "waf": "Operations" + }, + { + "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": "Azure Active Directory", - "text": "Minimize the use of password-based authentication for applications" + "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": "Identity", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "System or User assigned managed identities enable Azure SQLDB to authenticate to other cloud services (e.g. Azure Key Vault) without storing credentials in code. Once enabled, all necessary permissions can be granted via Azure role-based-access-control to the specific Azure SQLDB instance. Do not share user assigned managed identities across multiple services if not strictly required.", - "guid": "69891194-5074-4e30-8f69-4efc3c580900", - "link": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "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": "Managed Identities", - "text": "Assign Azure SQL Database a managed identity for outbound resource access" + "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": "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": [ + "Storage" + ], + "severity": "Low", + "subcategory": "Operations", + "text": "Use RWX storage with inbuilt Azure Files storage class.", + "waf": "Operations" }, { - "category": "Identity", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Use an Azure AD integrated authentication that eliminates the use of passwords. Password-based authentication methods are a weaker form of authentication. Credentials can be compromised or mistakenly given away. Use single sign-on authentication using Windows credentials. Federate the on-premises AD domain with Azure AD and use integrated Windows authentication (for domain-joined machines with Azure AD).", - "guid": "88287d4a-8bb8-4640-ad78-03f51354d003", - "link": "https://learn.microsoft.com/azure/azure-sql/database/authentication-aad-configure?view=azuresql&tabs=azure-powershell#active-directory-integrated-authentication", + "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": "Passwords", - "text": "Minimize the use of password-based authentication for users" + "subcategory": "Performance", + "text": "Use pod requests and limits to manage the compute resources within a cluster.", + "waf": "Performance" }, { - "category": "Ledger", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The hash of the latest block in the database ledger is called the database digest. It represents the state of all ledger tables in the database at the time when the block was generated. Generating a database digest is efficient, because it involves computing only the hashes of the blocks that were recently appended. Azure Confidential Ledger is one of the supported store, it can be used and supports automatic generation and storage of database digests. Azure Ledger provides advanced security features like Blockchain Ledger Proof and Confidential Hardware Enclaves. Use it only if advanced security features are required, otherwise revert to Azure storage.", - "guid": "0e853380-50ba-4bce-b2fd-5c7391c85ecc", - "link": "https://learn.microsoft.com/azure/architecture/guide/technology-choices/multiparty-computing-service#confidential-ledger-and-azure-blob-storage", + "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": "Database Digest", - "text": "Use Azure Confidential Ledger to store database digests only if advanced security features are required" + "subcategory": "Performance", + "text": "Enforce resource quotas on projects.", + "waf": "Performance" }, { - "category": "Ledger", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The hash of the latest block in the database ledger is called the database digest. It represents the state of all ledger tables in the database at the time when the block was generated. Generating a database digest is efficient, because it involves computing only the hashes of the blocks that were recently appended. Azure Blob Storage with Immutable Storage feature can be used and supports automatic generation and storage of database digests. To prevent tampering of your digest files, configure and lock a retention policy for your container.", - "guid": "afefb2d3-95da-4ac9-acf5-33d18b32ef9a", - "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-digest-management", - "severity": "Medium", - "subcategory": "Database Digest", - "text": "If Azure storage account is used to store database digests, ensure security is properly configured" + "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": "Ledger", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Ledger provides a form of data integrity called forward integrity, which provides evidence of data tampering on data in your ledger tables. The database verification process takes as input one or more previously generated database digests. It then recomputes the hashes stored in the database ledger based on the current state of the ledger tables. If the computed hashes don't match the input digests, the verification fails. The failure indicates that the data has been tampered with. The verification process reports all inconsistencies that it detects.", - "guid": "f8d4ffda-8aac-4cc6-b72b-c81cb8625420", - "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-database-verification", - "severity": "Medium", - "subcategory": "Integrity", - "text": "Schedule the Ledger verification process regularly to verify data integrity" + "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": [ + "VM" + ], + "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": "Ledger", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The Ledger feature provides tamper-evidence capabilities in your database. You can cryptographically attest to other parties, such as auditors or other business parties, that your data hasn't been tampered with. Ledger helps protect data from any attacker or high-privileged user, including database administrators (DBAs), system administrators, and cloud administrators.", - "guid": "2563f498-e2d3-42ea-9e7b-5517881a06a2", - "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-overview", - "severity": "Medium", - "subcategory": "Ledger", - "text": "If cryptographic proof of data integrity is a critical requirement, Ledger feature should be considered" + "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": "Ledger", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Depending on the type of tampering, there are cases where you can repair the ledger without losing data. In the article contained in the --More Info-- column, different scenarios and recovery techniques are described.", - "guid": "804fc554-6554-4842-91c1-713b32f99902", - "link": "https://learn.microsoft.com/sql/relational-databases/security/ledger/ledger-how-to-recover-after-tampering", - "severity": "Medium", - "subcategory": "Recovery", - "text": "Prepare a response plan to investigate and repair a database after a tampering event" + "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": [ + "Monitor" + ], + "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": "Logging", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Azure SQL Database Auditing tracks database events and writes them to an audit log in your Azure storage account. Auditing helps you understand database activity and gain insight into discrepancies and anomalies that could indicate business concerns or suspected security violations as well as helps you meet regulatory compliance. By default auditing policy includes all actions (queries, stored procedures and successful and failed logins) against the databases, which may result in high volume of audit logs. It's recommended for customers to configure auditing for different types of actions and action groups using PowerShell.", - "guid": "4082e31d-35f4-4a49-8507-d3172cc930a6", - "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", + "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": "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": [ + "AKS" + ], + "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": "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" + ], "severity": "Medium", - "subcategory": "Auditing", - "text": "Ensure that Azure SQL Database Auditing is enabled at the server level" + "subcategory": "Reliability", + "text": "Create application backup and plan for restore and include persistent volumes in the backup.", + "waf": "Reliability" }, { - "category": "Logging", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Azure SQL Database Auditing logs can be written to external storage accounts, Log Analytics workspace or Event Hub. Be sure to protect the target repository using backups and secured configuration. Use Azure SQL Database Managed Identity to access the storage and set an explicit retention period. Do not grant permissions to administrators to the audit log repository. Use a different target storage for --Enabling Auditing of Microsoft support operations--. ", - "guid": "9b64bc50-b60f-4035-bf7a-28c4806dfb46", - "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-overview", + "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": "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": [ + "AzurePolicy" + ], + "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": "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": [ + "ACR" + ], "severity": "Low", - "subcategory": "Auditing", - "text": "Ensure that Azure SQL Database Auditing logs are backed up and secured in the selected repository type" + "subcategory": "Security", + "text": "Store your container images in Azure Container Registry and geo-replicate the registry to each region.", + "waf": "Security" }, { - "category": "Logging", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The Azure Monitor activity log is a platform log in Azure that provides insight into subscription-level events. The activity log includes information like when a resource is modified. It is recommended to send this activity log to the same external storage repository as the Azure SQL Database Audit Log (storage account, Log Analytics workspace, Event Hub).", - "guid": "fcd34708-87ac-4efc-aaf6-57a47f76644a", - "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "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": "Auditing", - "text": "Ensure that Azure SQL Database Activity Log is collected and integrated with Auditing logs" + "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": "Logging", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Forward any logs from Azure SQL to your Security Information and Event Management (SIEM) and Security Orchestration Automation and Response (SOAR). Ensure that you are monitoring different types of Azure assets for potential threats and anomalies. Focus on getting high-quality alerts to reduce false positives for analysts to sort through. Alerts can be sourced from log data, agents, or other data.", - "guid": "f96e127e-9572-453a-b325-ff89ae9f6b44", - "link": "https://learn.microsoft.com/azure/azure-sql/database/auditing-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": [ + "Monitor" + ], "severity": "Medium", - "subcategory": "SIEM/SOAR", - "text": "Ensure that Azure SQL Database Auditing logs are being presented in to your organizations SIEM/SOAR" + "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": "Logging", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Forward any logs from Azure SQL to your Security Information and Event Management (SIEM) and Security Orchestration Automation and Response (SOAR), which can be used to set up custom threat detections. Ensure that you are monitoring different types of Azure assets for potential threats and anomalies. Focus on getting high-quality alerts to reduce false positives for analysts to sort through. Alerts can be sourced from log data, agents, or other data.", - "guid": "41503bf8-73da-4a10-af9f-5f7fceb5456f", - "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "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": "SIEM/SOAR", - "text": "Ensure that Azure SQL Database Activity Log data is presented in to your SIEM/SOAR" + "subcategory": "Workload", + "text": "Scale pods to meet demand using horizontal pod autoscaler.", + "waf": "Reliability" }, { - "category": "Logging", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Security Operation Center (SOC) team should create an incident response plan (playbooks or manual responses) to investigate and mitigate tampering, malicious activities, and other anomalous behaviors.", - "guid": "19ec7c97-c563-4e1d-82f0-54d6ec12e754", - "link": "https://learn.microsoft.com/azure/azure-monitor/essentials/activity-log", + "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" + ], "severity": "Medium", - "subcategory": "SIEM/SOAR", - "text": "Ensure that you have response plans for malicious or aberrant audit logging events" + "subcategory": "Workload", + "text": "Use disruption budgets to ensure the required number of pod replicas exist to handle expected application load.", + "waf": "Reliability" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "When you create a logical server from the Azure portal for Azure SQL Database, the result is a public endpoint that is visible and reachable over the public network (Public Access). You can then limit connectivity based on firewall rules and Service Endpoint. You can also configure private connectivity only limiting connections to internal networks using Private Endpoint (Private Access). Private Access using Private Endpoint should be the default unless a business case or performance/technical reason applies that cannot support it. Usage of Private Endpoints has performance implications that need to be considered and assessed.", - "guid": "2c6d356a-1784-475b-a42c-ec187dc8c925", - "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview", - "severity": "High", - "subcategory": "Connectivity", - "text": "Review Public vs. Private Access connectivity methods and select the appropriate one for the workload" + "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": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "IMPORTANT: Connections to private endpoint only support Proxy as the connection policy. When using private endpoints connections are proxied via the Azure SQL Database gateway to the database nodes. Clients will not have a direct connection.", - "guid": "557b3ce5-bada-4296-8d52-a2d447bc1718", - "link": "https://learn.microsoft.com/azure/azure-sql/database/connectivity-architecture", + "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": "Connectivity", - "text": "Keep default Azure SQL Database Connection Policy if not differently required and justified" + "subcategory": "Workload", + "text": "Consider blue/green or canary strategies to deploy new releases of application.", + "waf": "Operations" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "This option configures the firewall to allow all connections from Azure, including connections from the subscriptions of other customers. If you select this option, make sure that your login and user permissions limit access to authorized users only. If not strictly required, keep this setting to OFF.", - "guid": "f48efacf-4405-4e8d-9dd0-16c5302ed082", - "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview", + "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": "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": "Connectivity", - "text": "Ensure Allow Azure Services and Resources to Access this Server setting is disabled in Azure SQL Database firewall" + "subcategory": "Control plane", + "text": "Keep your clusters on the latest OpenShift version to avoid potential security or upgrade issues.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Azure SQL Database has a new built-in feature that allows native integration with external REST endpoints. This means that integration of Azure SQL Database with Azure Functions, Azure Logic Apps, Cognitive Services, Event Hubs, Event Grid, Azure Containers, API Management and in general any REST or even GraphQL endpoint. If not properly restricted, code inside an Azure SQL Database database could leverage this mechanism to exfiltrate data. If not strictly required, it is recommended to block or restrict this feature using Outbound Firewall Rules.", - "guid": "cb3274a7-e36d-46f6-8de5-46d30c8dde8e", - "link": "https://learn.microsoft.com/sql/relational-databases/system-stored-procedures/sp-invoke-external-rest-endpoint-transact-sql", - "severity": "Medium", - "subcategory": "Outbound Control", - "text": "Block or restrict outbound REST API calls to external endpoints" + "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": [ + "Arc", + "AKS" + ], + "severity": "High", + "subcategory": "Control plane", + "text": "Connect Azure Red Hat OpenShift clusters to Azure Arc-enabled Kubernetes.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Outbound firewall rules limit network traffic from the Azure SQL Database logical server to a customer defined list of Azure Storage accounts and Azure SQL Database logical servers. Any attempt to access storage accounts or databases not in this list is denied.", - "guid": "a566dd3d-314e-4a94-9378-102c42d82b38", - "link": "https://learn.microsoft.com/azure/azure-sql/database/outbound-firewall-rule-overview", - "severity": "Medium", - "subcategory": "Outbound Control", - "text": "If outbound network access is required, it is recommended to configure outbound networking restrictions using built-in Azure SQL Database control feature" + "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": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Private Endpoint is created inside a subnet in an Azure Virtual Network. Proper security configuration must be applied also to the containing network environment, including NSG/ASG, UDR, firewall, monitoring and auditing.", - "guid": "246cd832-f550-4af0-9c74-ca9baeeb8860", - "link": "https://learn.microsoft.com/azure/azure-sql/database/private-endpoint-overview?view=azuresql#disable-public-access-to-your-logical-server", + "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": [ + "Arc", + "Defender", + "AKS" + ], "severity": "Medium", - "subcategory": "Private Access", - "text": "If Private Access connectivity is used, ensure that you are using the Private Endpoint, Azure Virtual Network, Azure Firewall, and Azure Network Security Group checklists" + "subcategory": "Posture", + "text": "Use Microsoft Defender for Containers supported via Arc-enabled Kubernetes to secure clusters, containers, and applications.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "When adding a Private Endpoint connection, public routing to your logical server isn't blocked by default. In the --Firewall and virtual networks-- pane, the setting --Deny public network access-- is not selected by default. To disable public network access, ensure that you select --Deny public network access--.", - "guid": "3a0808ee-ea7a-47ab-bdce-920a6a2b3881", - "link": "https://learn.microsoft.com/azure/azure-sql/database/private-endpoint-overview?view=azuresql#disable-public-access-to-your-logical-server", - "severity": "High", - "subcategory": "Private Access", - "text": "If Private Endpoint (Private Access) is used, consider disabling Public Access connectivity" + "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": [ + "Arc", + "AKS", + "AKV" + ], + "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": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Network Security Group (NSG) and Application Security Group (ASG) can be now applied to subnet containing Private Endpoints to restrict connections to Azure SQLDB based on internal source IP ranges.", - "guid": "8600527e-e8c4-4424-90ef-1f0dca0224f2", - "link": "https://learn.microsoft.com/azure/private-link/private-endpoint-overview#network-security-of-private-endpoints", + "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": "Private Access", - "text": "If Private Endpoint (Private Access) is used, apply NSG and eventually ASG to limit incoming source IP address ranges" + "subcategory": "Workload", + "text": "Secure pod access to resources. Provide the least number of permissions, and avoid using root or privileged escalation.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "A Managed Instance (SQL MI) can be isolated inside a virtual network to prevent external access. Applications and tools that are in the same or peered virtual network in the same region could access it directly. Applications and tools that are in different region could use virtual-network-to-virtual-network connection or ExpressRoute circuit peering to establish connection. Customer should use Network Security Groups (NSG), and eventually internal firewalls, to restrict access over port 1433 only to resources that require access to a managed instance.", - "guid": "18123ef4-a0a6-45e3-87fe-7f454f65d975", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/connectivity-architecture-overview", + "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": [ + "AzurePolicy", + "Monitor" + ], "severity": "Medium", - "subcategory": "Private Access", - "text": "Apply Network Security Groups (NSG) and firewall rules to restrict access to Azure SQL Managed Instance internal subnet" + "subcategory": "Workload", + "text": "Monitor and enforce configuration by using the Azure Policy Extension.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Azure Virtual Network Service Endpoint is preferred solution if you want to establish a direct connection to the Azure SQL Database backend nodes using Redirect policy. This will allow access in high performance mode and is the recommended approach from a performance perspective.", - "guid": "55187443-6852-4fbd-99c6-ce303597ca7f", - "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview?view=azuresql#ip-vs-virtual-network-firewall-rules", + "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": [ + "Defender" + ], "severity": "High", - "subcategory": "Public Access", - "text": "If Public Access connectivity is used, leverage Service Endpoint to restrict access from selected Azure Virtual Networks" + "subcategory": "Workload", + "text": "Scan your images for vulnerabilities with Microsoft Defender or any other image scanning solution.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The Azure SQL Database firewall allows you to specify IP address ranges from which communications are accepted. This approach is fine for stable IP addresses that are outside the Azure private network.", - "guid": "a73e32da-b3f4-4960-b5ec-2f42a557bf31", - "link": "https://learn.microsoft.com/azure/azure-sql/database/network-access-controls-overview", - "severity": "Medium", - "subcategory": "Public Access", - "text": "If Public Access connectivity is used, ensure that only specific known IPs are added to the firewall" + "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": [ + "ACR", + "Subscriptions" + ], + "severity": "Low", + "subcategory": "Workload", + "text": "Deploy a dedicated and private instance of Azure Container Registry to each landing zone subscription.", + "waf": "Security" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "We recommend that you use database-level IP firewall rules whenever possible. This practice enhances security and makes your database more portable. Use server-level IP firewall rules for administrators. Also use them when you have many databases that have the same access requirements, and you don't want to configure each database individually.", - "guid": "e0f31ac9-35c8-4bfd-9865-edb60ffc6768", - "link": "https://learn.microsoft.com/azure/azure-sql/database/firewall-configure", + "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": [ + "EventHubs" + ], "severity": "Low", - "subcategory": "Public Access", - "text": "If Public Access connectivity is used and controlled by Azure SQL Database firewall rules, use database-level over server-level IP rules" + "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": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "A Managed Instance (SQL MI) can be isolated inside a virtual network to prevent external access. The Managed Instance public endpoint is not enabled by default, must be explicitly enabled, only if strictly required. If company policy disallows the use of public endpoints, use Azure Policy to prevent enabling public endpoints in the first place.", - "guid": "b8435656-143e-41a8-9922-61d34edb751a", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/public-endpoint-overview", - "severity": "High", - "subcategory": "Public Access", - "text": "Do not enable Azure SQL Managed Instance public endpoint" + "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" + ], + "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/" }, { - "category": "Networking", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "A Managed Instance (SQL MI) public endpoint is not enabled by default, must be explicitly enabled, only if strictly required. In this case, it is recommended to apply a Network Security Groups (NSG) to restrict access to port 3342 only to trusted source IP addresses.", - "guid": "057dd298-8726-4aa6-b590-1f81d2e30421", - "link": "https://learn.microsoft.com/azure/azure-sql/managed-instance/public-endpoint-overview", + "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": [ + "AzurePolicy", + "Entra", + "RBAC", + "EventHubs", + "TrafficManager" + ], + "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": "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": [ + "VM", + "AKV", + "Storage", + "Entra", + "EventHubs" + ], + "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/" + }, + { + "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": [ + "EventHubs", + "RBAC", + "Entra" + ], "severity": "High", - "subcategory": "Public Access", - "text": "Restrict access if Azure SQL Managed Instance public endpoint is required" + "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": "Privileged Access", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Most operations, support, and troubleshooting performed by Microsoft personnel and sub-processors do not require access to customer data. In those rare circumstances where such access is required, Customer Lockbox for Microsoft Azure provides an interface for customers to review and approve or reject customer data access requests. In support scenarios where Microsoft needs to access customer data, Azure SQL Database supports Customer Lockbox to provide an interface for you to review and approve or reject customer data access requests.", - "guid": "37b6eb0f-553d-488f-8a8a-cb9bf97388ff", - "link": "https://learn.microsoft.com/azure/security/fundamentals/customer-lockbox-overview", - "severity": "Low", - "subcategory": "Lockbox", - "text": "Review and enable Customer Lockbox for Azure SQL Database access by Microsoft personnel" + "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": "Privileged Access", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "The principle of least privilege states that users shouldn't have more privileges than needed to complete their tasks. High-privileged database and server users can perform many configuration and maintenance activities on the database and can also drop databases in Azure SQL instance. Tracking database owners and privileged accounts is important to avoid having excessive permission.", - "guid": "5fe5281f-f0f9-4842-a682-8baf18bd8316", - "link": "https://learn.microsoft.com/azure/azure-sql/database/security-best-practice?view=azuresql#implement-principle-of-least-privilege", + "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": [ + "VNet", + "EventHubs", + "PrivateLink" + ], "severity": "Medium", - "subcategory": "Permissions", - "text": "Ensure that users are assigned the minimum level of access necessarily to complete their job functions" + "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": "Privileged Access", - "checklist": "Azure SQLDB Security Checklist (Preview)", - "description": "Identities (both Users and SPNs) should be scoped to the least amount of access needed to perform the function. A higher number of tightly scoped SPNs should be used, instead of having one SPN with multiple sets of unrelated permissions. For example, if there are three external web applications hosted on-prem that make queries to the Azure SQL Database, they should not all use the same SPN for these activities. Instead, they should each have their own tightly scoped SPN.", - "guid": "7b5b55e5-4750-4920-be97-eb726c256a5c", - "link": "https://learn.microsoft.com/security/benchmark/azure/baselines/sql-database-security-baseline#im-3-use-azure-ad-single-sign-on-sso-for-application-access", - "severity": "Low", - "subcategory": "Permissions", - "text": "Ensure that distinct applications will be assigned different credentials with minimal permissions to access Azure SQL Database" + "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/" } ], "metadata": { "name": "Master checklist", - "timestamp": "March 17, 2023" + "timestamp": "October 20, 2023" }, "severities": [ { diff --git a/spreadsheet/macrofree/aks_checklist.en.xlsx b/spreadsheet/macrofree/aks_checklist.en.xlsx index be6e08ac7..0ed6e5874 100644 Binary files a/spreadsheet/macrofree/aks_checklist.en.xlsx and b/spreadsheet/macrofree/aks_checklist.en.xlsx differ diff --git a/spreadsheet/macrofree/aks_checklist.es.xlsx b/spreadsheet/macrofree/aks_checklist.es.xlsx index 7e2c35e1e..421a34a7c 100644 Binary files a/spreadsheet/macrofree/aks_checklist.es.xlsx and b/spreadsheet/macrofree/aks_checklist.es.xlsx differ diff --git a/spreadsheet/macrofree/aks_checklist.ja.xlsx b/spreadsheet/macrofree/aks_checklist.ja.xlsx index f2a3d20e3..3a58812d8 100644 Binary files a/spreadsheet/macrofree/aks_checklist.ja.xlsx and b/spreadsheet/macrofree/aks_checklist.ja.xlsx differ diff --git a/spreadsheet/macrofree/aks_checklist.ko.xlsx b/spreadsheet/macrofree/aks_checklist.ko.xlsx index 10235477c..c1a9cdc29 100644 Binary files a/spreadsheet/macrofree/aks_checklist.ko.xlsx and b/spreadsheet/macrofree/aks_checklist.ko.xlsx differ diff --git a/spreadsheet/macrofree/aks_checklist.pt.xlsx b/spreadsheet/macrofree/aks_checklist.pt.xlsx index fd1411ab5..0ca5c02e7 100644 Binary files a/spreadsheet/macrofree/aks_checklist.pt.xlsx and b/spreadsheet/macrofree/aks_checklist.pt.xlsx differ diff --git a/spreadsheet/macrofree/checklist.en.master.xlsx b/spreadsheet/macrofree/checklist.en.master.xlsx index 30985cec4..62fce0016 100644 Binary files a/spreadsheet/macrofree/checklist.en.master.xlsx and b/spreadsheet/macrofree/checklist.en.master.xlsx differ diff --git a/workbooks/aks_checklist.en_counters_workbook.json b/workbooks/aks_checklist.en_counters_workbook.json index fe8ac7aed..ed6275dab 100644 --- a/workbooks/aks_checklist.en_counters_workbook.json +++ b/workbooks/aks_checklist.en_counters_workbook.json @@ -1127,7 +1127,7 @@ "style": "tabs", "links": [ { - "id": "de06b97b-4118-4a16-87f9-07066e583f12", + "id": "18ceb1b9-aff7-498b-9127-c272a3c5ebb5", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Identity and Access Management ({Tab0Success:value}/{Tab0Total:value})", @@ -1136,7 +1136,7 @@ "style": "primary" }, { - "id": "f24e18d1-b273-47ae-8b36-c99ca9a8724b", + "id": "b6844e95-e308-4b7e-b50c-3c83026dc4a2", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity ({Tab1Success:value}/{Tab1Total:value})", @@ -1145,7 +1145,7 @@ "style": "primary" }, { - "id": "f6f50123-6f7b-4445-8472-b5850f132e18", + "id": "10ffd080-1dde-40f9-a902-50ea057b2435", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "BC and DR ({Tab2Success:value}/{Tab2Total:value})", @@ -1154,7 +1154,7 @@ "style": "primary" }, { - "id": "f753d9c5-8f2a-471a-9f68-7edf72404ae3", + "id": "f2562306-088e-44a9-9642-7495324bace5", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Governance and Security ({Tab3Success:value}/{Tab3Total:value})", @@ -1163,7 +1163,7 @@ "style": "primary" }, { - "id": "fe858349-43b7-4ed0-8eb3-b985df2f823b", + "id": "5b99f218-9d30-4095-803c-9432da68d2ab", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Operations ({Tab4Success:value}/{Tab4Total:value})", diff --git a/workbooks/aks_checklist.en_counters_workbook_template.json b/workbooks/aks_checklist.en_counters_workbook_template.json index 810518591..fd3c4f05f 100644 --- a/workbooks/aks_checklist.en_counters_workbook_template.json +++ b/workbooks/aks_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.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1)| 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | 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\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | 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\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | 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\": \"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.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')| 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.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')| 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | 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\": \"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\": \"Query23Stats\",\n \"type\": 1,\n \"query\": \"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| 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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.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\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.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\": \"{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.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\": \"{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.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}\"\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}\"\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\": \"{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\": \"{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 \"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}+{Query22Stats:$.Success}+{Query23Stats:$.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}+{Query22Stats:$.Total}+{Query23Stats:$.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\": \"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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.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\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.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 AKS Review\\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\": \"de06b97b-4118-4a16-87f9-07066e583f12\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Identity and Access Management ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Identity and Access Management\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f24e18d1-b273-47ae-8b36-c99ca9a8724b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f6f50123-6f7b-4445-8472-b5850f132e18\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"BC and DR ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"BC and DR\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f753d9c5-8f2a-471a-9f68-7edf72404ae3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Governance and Security ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Governance and Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"fe858349-43b7-4ed0-8eb3-b985df2f823b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Operations ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Operations\",\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\": \"## Identity and Access Management\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use managed identities instead of Service Principals. Check [this link](https://learn.microsoft.com/azure/aks/use-managed-identity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Integrate authentication with AAD (using the managed integration). Check [this link](https://learn.microsoft.com/azure/aks/managed-aad) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | 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\": \"Disable AKS local accounts. Check [this link](https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==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\": \"query6\"\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\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Do not use AKS Application Routing Add-On. Check [this link](https://learn.microsoft.com/azure/aks/http-application-routing) for further information.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows workloads use Accelerated Networking. Check [this link](https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview) for further information.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Use the standard ALB (as opposed to the basic one). Check [this link](https://learn.microsoft.com/azure/aks/load-balancer-standard) for further information.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | 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\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Choose the best CNI network plugin for your requirements (Azure CNI recommended). Check [this link](https://learn.microsoft.com/azure/aks/operator-best-practices-network) for further information.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | 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\": \"query10\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Filter egress traffic with AzFW/NVA if your security requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/limit-egress-traffic) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | 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\": \"If using a public API endpoint, restrict the IP addresses that can access it. Check [this link](https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | 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 private clusters if your requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/private-clusters) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used. Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enable a Kubernetes Network Policy option (Calico/Azure). Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | 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\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use DDoS Standard in the AKS Virtual Network. Check [this link](https://learn.microsoft.com/azure/virtual-network/ddos-protection-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.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') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"If required add company HTTP Proxy. Check [this link](https://learn.microsoft.com/azure/aks/http-proxy) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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') | 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\": \"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\": \"## BC and DR\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Availability Zones if they are supported in your Azure region. Check [this link](https://learn.microsoft.com/azure/aks/availability-zones) 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.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | 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\": \"Use the SLA-backed AKS offering. Check [this link](https://learn.microsoft.com/azure/aks/uptime-sla) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | 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 },\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\": \"## Governance and Security\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Policy for Kubernetes to ensure cluster compliance. Check [this link](https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==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\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Separate applications from the control plane with user/system nodepools. Check [this link](https://learn.microsoft.com/azure/aks/use-system-pools) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1) | 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\": \"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\": \"## Operations\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use custom Node RG (aka 'Infra RG') name. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | 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\": \"Consider AKS virtual node for quick bursting. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==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\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch). Check [this link](https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==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\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the Cluster Autoscaler. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | 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\": \"query21\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Customize node configuration for AKS node pools. Check [this link](https://learn.microsoft.com/azure/aks/custom-node-configuration) for further information.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | 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\": \"query22\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use ephemeral OS disks. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext23\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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 | 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\": \"query23\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\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.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1)| 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | 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\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | 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\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | 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\": \"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.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')| 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.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')| 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | 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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | 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\": \"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\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | 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\": \"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\": \"Query23Stats\",\n \"type\": 1,\n \"query\": \"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| 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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.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\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.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\": \"{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.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\": \"{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.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}\"\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}\"\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\": \"{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\": \"{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 \"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}+{Query22Stats:$.Success}+{Query23Stats:$.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}+{Query22Stats:$.Total}+{Query23Stats:$.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\": \"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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.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\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.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 AKS Review\\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\": \"18ceb1b9-aff7-498b-9127-c272a3c5ebb5\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Identity and Access Management ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Identity and Access Management\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b6844e95-e308-4b7e-b50c-3c83026dc4a2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"10ffd080-1dde-40f9-a902-50ea057b2435\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"BC and DR ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"BC and DR\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f2562306-088e-44a9-9642-7495324bace5\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Governance and Security ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Governance and Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5b99f218-9d30-4095-803c-9432da68d2ab\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Operations ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Operations\",\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\": \"## Identity and Access Management\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use managed identities instead of Service Principals. Check [this link](https://learn.microsoft.com/azure/aks/use-managed-identity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Integrate authentication with AAD (using the managed integration). Check [this link](https://learn.microsoft.com/azure/aks/managed-aad) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | 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\": \"Disable AKS local accounts. Check [this link](https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==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\": \"query6\"\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\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Do not use AKS Application Routing Add-On. Check [this link](https://learn.microsoft.com/azure/aks/http-application-routing) for further information.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows workloads use Accelerated Networking. Check [this link](https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview) for further information.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Use the standard ALB (as opposed to the basic one). Check [this link](https://learn.microsoft.com/azure/aks/load-balancer-standard) for further information.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | 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\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Choose the best CNI network plugin for your requirements (Azure CNI recommended). Check [this link](https://learn.microsoft.com/azure/aks/operator-best-practices-network) for further information.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | 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\": \"query10\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Filter egress traffic with AzFW/NVA if your security requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/limit-egress-traffic) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | 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\": \"If using a public API endpoint, restrict the IP addresses that can access it. Check [this link](https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | 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 private clusters if your requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/private-clusters) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used. Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enable a Kubernetes Network Policy option (Calico/Azure). Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | 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\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use DDoS Standard in the AKS Virtual Network. Check [this link](https://learn.microsoft.com/azure/virtual-network/ddos-protection-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.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') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"If required add company HTTP Proxy. Check [this link](https://learn.microsoft.com/azure/aks/http-proxy) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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') | 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\": \"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\": \"## BC and DR\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Availability Zones if they are supported in your Azure region. Check [this link](https://learn.microsoft.com/azure/aks/availability-zones) 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.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | 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\": \"Use the SLA-backed AKS offering. Check [this link](https://learn.microsoft.com/azure/aks/uptime-sla) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | 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 },\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\": \"## Governance and Security\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Policy for Kubernetes to ensure cluster compliance. Check [this link](https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==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\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Separate applications from the control plane with user/system nodepools. Check [this link](https://learn.microsoft.com/azure/aks/use-system-pools) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1) | 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\": \"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\": \"## Operations\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use custom Node RG (aka 'Infra RG') name. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | 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\": \"Consider AKS virtual node for quick bursting. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==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\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch). Check [this link](https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==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\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the Cluster Autoscaler. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | 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\": \"query21\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Customize node configuration for AKS node pools. Check [this link](https://learn.microsoft.com/azure/aks/custom-node-configuration) for further information.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | 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\": \"query22\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use ephemeral OS disks. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext23\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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 | 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\": \"query23\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\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/aks_checklist.en_workbook.json b/workbooks/aks_checklist.en_workbook.json index 725b90d6d..bd709e1c6 100644 --- a/workbooks/aks_checklist.en_workbook.json +++ b/workbooks/aks_checklist.en_workbook.json @@ -70,7 +70,7 @@ "style": "tabs", "links": [ { - "id": "053cf1b2-791f-45b0-b80c-98637dff4552", + "id": "2eb7ec82-9180-4afd-b139-b5a79c1407d3", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Identity and Access Management", @@ -79,7 +79,7 @@ "style": "primary" }, { - "id": "49403925-969e-414d-ad02-ba1f7659b57f", + "id": "979351e8-3156-420d-8fb6-61d3b6c1ce5d", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity", @@ -88,7 +88,7 @@ "style": "primary" }, { - "id": "725f8a8d-f23e-49e1-bcb3-2c95e82c0f7c", + "id": "a95e3c57-7b90-427f-a55c-0bde8e116ff0", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "BC and DR", @@ -97,7 +97,7 @@ "style": "primary" }, { - "id": "bb92a87c-9cc3-49db-b265-add80eb5c51c", + "id": "7010101a-3509-4275-a8fb-4cd4e408e2a3", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Governance and Security", @@ -106,7 +106,7 @@ "style": "primary" }, { - "id": "7247f5db-017b-49de-be9e-3e9568e600d2", + "id": "18450720-da74-4309-abdd-1bbee4c35fee", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Operations", diff --git a/workbooks/aks_checklist.en_workbook_template.json b/workbooks/aks_checklist.en_workbook_template.json index b79a8e632..86566f9b2 100644 --- a/workbooks/aks_checklist.en_workbook_template.json +++ b/workbooks/aks_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 AKS Review\\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\": \"053cf1b2-791f-45b0-b80c-98637dff4552\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Identity and Access Management\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Identity and Access Management\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"49403925-969e-414d-ad02-ba1f7659b57f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"725f8a8d-f23e-49e1-bcb3-2c95e82c0f7c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"BC and DR\",\n \"subTarget\": \"tab2\",\n \"preText\": \"BC and DR\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"bb92a87c-9cc3-49db-b265-add80eb5c51c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Governance and Security\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Governance and Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"7247f5db-017b-49de-be9e-3e9568e600d2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Operations\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Operations\",\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\": \"## Identity and Access Management\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use managed identities instead of Service Principals. Check [this link](https://learn.microsoft.com/azure/aks/use-managed-identity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Integrate authentication with AAD (using the managed integration). Check [this link](https://learn.microsoft.com/azure/aks/managed-aad) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | 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\": \"Disable AKS local accounts. Check [this link](https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==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\": \"query6\"\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\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Do not use AKS Application Routing Add-On. Check [this link](https://learn.microsoft.com/azure/aks/http-application-routing) for further information.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows workloads use Accelerated Networking. Check [this link](https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview) for further information.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Use the standard ALB (as opposed to the basic one). Check [this link](https://learn.microsoft.com/azure/aks/load-balancer-standard) for further information.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | 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\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Choose the best CNI network plugin for your requirements (Azure CNI recommended). Check [this link](https://learn.microsoft.com/azure/aks/operator-best-practices-network) for further information.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | 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\": \"query10\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Filter egress traffic with AzFW/NVA if your security requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/limit-egress-traffic) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | 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\": \"If using a public API endpoint, restrict the IP addresses that can access it. Check [this link](https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | 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 private clusters if your requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/private-clusters) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used. Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enable a Kubernetes Network Policy option (Calico/Azure). Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | 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\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use DDoS Standard in the AKS Virtual Network. Check [this link](https://learn.microsoft.com/azure/virtual-network/ddos-protection-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.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') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"If required add company HTTP Proxy. Check [this link](https://learn.microsoft.com/azure/aks/http-proxy) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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') | 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\": \"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\": \"## BC and DR\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Availability Zones if they are supported in your Azure region. Check [this link](https://learn.microsoft.com/azure/aks/availability-zones) 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.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | 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\": \"Use the SLA-backed AKS offering. Check [this link](https://learn.microsoft.com/azure/aks/uptime-sla) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | 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 },\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\": \"## Governance and Security\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Policy for Kubernetes to ensure cluster compliance. Check [this link](https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==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\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Separate applications from the control plane with user/system nodepools. Check [this link](https://learn.microsoft.com/azure/aks/use-system-pools) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1) | 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\": \"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\": \"## Operations\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use custom Node RG (aka 'Infra RG') name. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | 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\": \"Consider AKS virtual node for quick bursting. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==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\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch). Check [this link](https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==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\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the Cluster Autoscaler. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | 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\": \"query21\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Customize node configuration for AKS node pools. Check [this link](https://learn.microsoft.com/azure/aks/custom-node-configuration) for further information.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | 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\": \"query22\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use ephemeral OS disks. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext23\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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 | 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\": \"query23\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\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 AKS Review\\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\": \"2eb7ec82-9180-4afd-b139-b5a79c1407d3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Identity and Access Management\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Identity and Access Management\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"979351e8-3156-420d-8fb6-61d3b6c1ce5d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a95e3c57-7b90-427f-a55c-0bde8e116ff0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"BC and DR\",\n \"subTarget\": \"tab2\",\n \"preText\": \"BC and DR\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"7010101a-3509-4275-a8fb-4cd4e408e2a3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Governance and Security\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Governance and Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"18450720-da74-4309-abdd-1bbee4c35fee\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Operations\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Operations\",\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\": \"## Identity and Access Management\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use managed identities instead of Service Principals. Check [this link](https://learn.microsoft.com/azure/aks/use-managed-identity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.servicePrincipalProfile.clientId=='msi') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Integrate authentication with AAD (using the managed integration). Check [this link](https://learn.microsoft.com/azure/aks/managed-aad) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.aadProfile) | 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\": \"Disable AKS local accounts. Check [this link](https://learn.microsoft.com/azure/aks/managed-aad#disable-local-accounts) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.disableLocalAccounts==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\": \"query6\"\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\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Do not use AKS Application Routing Add-On. Check [this link](https://learn.microsoft.com/azure/aks/http-application-routing) for further information.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows workloads use Accelerated Networking. Check [this link](https://learn.microsoft.com/azure/virtual-network/accelerated-networking-overview) for further information.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnull(properties.addonProfiles.httpApplicationRouting) or properties.addonProfiles.httpApplicationRouting.enabled==false) | 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 \"type\": 1,\n \"content\": {\n \"json\": \"Use the standard ALB (as opposed to the basic one). Check [this link](https://learn.microsoft.com/azure/aks/load-balancer-standard) for further information.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (tolower(properties.networkProfile.loadBalancerSku)=='standard') | 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\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Choose the best CNI network plugin for your requirements (Azure CNI recommended). Check [this link](https://learn.microsoft.com/azure/aks/operator-best-practices-network) for further information.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.networkPlugin=='azure') | 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\": \"query10\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Filter egress traffic with AzFW/NVA if your security requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/limit-egress-traffic) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.networkProfile.outboundType=='userDefinedRouting') | 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\": \"If using a public API endpoint, restrict the IP addresses that can access it. Check [this link](https://learn.microsoft.com/azure/aks/api-server-authorized-ip-ranges) for further information.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = ((isnull(properties.apiServerAccessProfile.enablePrivateCluster) or properties.apiServerAccessProfile.enablePrivateCluster==false) and isnotnull(properties.apiServerAccessProfile.authorizedIPRanges)) | 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 private clusters if your requirements mandate it. Check [this link](https://learn.microsoft.com/azure/aks/private-clusters) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For Windows 2019 and 2022 AKS nodes Calico Network Policies can be used. Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | where isnotnull(properties.apiServerAccessProfile.enablePrivateCluster) | extend compliant = (properties.apiServerAccessProfile.enablePrivateCluster==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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enable a Kubernetes Network Policy option (Calico/Azure). Check [this link](https://learn.microsoft.com/azure/aks/use-network-policies) for further information.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = isnotnull(properties.networkProfile.networkPolicy) | 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\": \"query15\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use DDoS Standard in the AKS Virtual Network. Check [this link](https://learn.microsoft.com/azure/virtual-network/ddos-protection-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.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') | 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 \"type\": 1,\n \"content\": {\n \"json\": \"If required add company HTTP Proxy. Check [this link](https://learn.microsoft.com/azure/aks/http-proxy) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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') | 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\": \"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\": \"## BC and DR\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Availability Zones if they are supported in your Azure region. Check [this link](https://learn.microsoft.com/azure/aks/availability-zones) 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.containerservice/managedclusters' | extend compliant= isnotnull(properties.agentPoolProfiles[0].availabilityZones) | 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\": \"Use the SLA-backed AKS offering. Check [this link](https://learn.microsoft.com/azure/aks/uptime-sla) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (sku.tier=='Paid') | 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 },\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\": \"## Governance and Security\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Policy for Kubernetes to ensure cluster compliance. Check [this link](https://learn.microsoft.com/azure/governance/policy/concepts/policy-for-kubernetes) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.azurepolicy) and properties.addonProfiles.azurepolicy.enabled==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\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Separate applications from the control plane with user/system nodepools. Check [this link](https://learn.microsoft.com/azure/aks/use-system-pools) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | project id,resourceGroup,name,pools=properties.agentPoolProfiles | project id,name,resourceGroup,poolcount=array_length(pools) | extend compliant = (poolcount > 1) | 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\": \"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\": \"## Operations\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use custom Node RG (aka 'Infra RG') name. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (properties.nodeResourceGroup !startswith 'MC_') | 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\": \"Consider AKS virtual node for quick bursting. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.aciConnectorLinux) and properties.addonProfiles.aciConnectorLinux.enabled==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\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Store and analyze your cluster logs with Container Insights (or other tools like Telegraf/ElasticSearch). Check [this link](https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.addonProfiles.omsagent) and properties.addonProfiles.omsagent.enabled==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\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the Cluster Autoscaler. Check [this link](https://learn.microsoft.com/azure/aks/concepts-scale) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.autoScalerProfile)) | 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\": \"query21\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Customize node configuration for AKS node pools. Check [this link](https://learn.microsoft.com/azure/aks/custom-node-configuration) for further information.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"where type=='microsoft.containerservice/managedclusters' | extend compliant = (isnotnull(properties.austoscalerProfile)) | 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\": \"query22\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use ephemeral OS disks. Check [this link](https://learn.microsoft.com/azure/aks/cluster-configuration) for further information.\"\n },\n \"name\": \"querytext23\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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 | 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\": \"query23\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\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_counters.json b/workbooks/alz_checklist.en_network_counters.json index ef1465766..b2525c848 100644 --- a/workbooks/alz_checklist.en_network_counters.json +++ b/workbooks/alz_checklist.en_network_counters.json @@ -861,7 +861,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query27Stats:$.Success}" } } ] @@ -880,7 +880,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query27Stats:$.Total}" } } ] @@ -918,7 +918,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" } } ] @@ -937,7 +937,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" } } ] @@ -975,7 +975,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -994,7 +994,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -1032,7 +1032,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" } } ] @@ -1051,7 +1051,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" } } ] @@ -1146,7 +1146,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" } } ] @@ -1165,7 +1165,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" } } ] @@ -1203,7 +1203,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" + "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -1222,7 +1222,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" + "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -1260,7 +1260,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" + "resultVal": "{Query22Stats:$.Success}" } } ] @@ -1279,7 +1279,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" + "resultVal": "{Query22Stats:$.Total}" } } ] @@ -1317,7 +1317,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query22Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query27Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" + "resultVal": "{Query27Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}" } } ] @@ -1336,7 +1336,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query22Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query27Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" + "resultVal": "{Query27Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}" } } ] @@ -1410,43 +1410,43 @@ "style": "tabs", "links": [ { - "id": "6ad79203-5d04-44eb-82ea-b2803bc6aaaa", + "id": "7f5af678-bf5f-414f-85d9-c83cf5e36b91", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke ({Tab0Success:value}/{Tab0Total:value})", + "linkLabel": "Virtual WAN ({Tab0Success:value}/{Tab0Total:value})", "subTarget": "tab0", - "preText": "Hub and spoke", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "96043720-2da6-41fe-aef0-41ed83a4fe47", + "id": "bf90ac83-c8ee-43d3-9f2d-16b012c45255", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan ({Tab1Success:value}/{Tab1Total:value})", + "linkLabel": "Hybrid ({Tab1Success:value}/{Tab1Total:value})", "subTarget": "tab1", - "preText": "IP plan", + "preText": "Hybrid", "style": "primary" }, { - "id": "e53bf286-5a18-4556-9773-1289b816afee", + "id": "a5401b49-46e8-4a4f-a975-e1afb0df0128", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS ({Tab2Success:value}/{Tab2Total:value})", + "linkLabel": "Hub and spoke ({Tab2Success:value}/{Tab2Total:value})", "subTarget": "tab2", - "preText": "PaaS", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "5c17439a-9f1b-4961-b778-b7bea030f9fa", + "id": "86f08cd3-4078-495c-9863-9923e6139d4d", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet ({Tab3Success:value}/{Tab3Total:value})", + "linkLabel": "IP plan ({Tab3Success:value}/{Tab3Total:value})", "subTarget": "tab3", - "preText": "Internet", + "preText": "IP plan", "style": "primary" }, { - "id": "f4da2b21-2915-4c30-8585-482cc5168b19", + "id": "b77ebfcc-e5a7-4db9-8567-9a03e3473f5e", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "App delivery ({Tab4Success:value}/{Tab4Total:value})", @@ -1455,30 +1455,30 @@ "style": "primary" }, { - "id": "a65a5b87-fb52-484d-88d3-032c381baa19", + "id": "a80b762c-170f-4b03-81dd-3075236c8d5e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN ({Tab5Success:value}/{Tab5Total:value})", + "linkLabel": "Segmentation ({Tab5Success:value}/{Tab5Total:value})", "subTarget": "tab5", - "preText": "Virtual WAN", + "preText": "Segmentation", "style": "primary" }, { - "id": "955b94c2-87b3-484b-8c9f-a44ab1129e66", + "id": "858f7163-8c75-4143-8ec7-08ffaad8cb51", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation ({Tab6Success:value}/{Tab6Total:value})", + "linkLabel": "Internet ({Tab6Success:value}/{Tab6Total:value})", "subTarget": "tab6", - "preText": "Segmentation", + "preText": "Internet", "style": "primary" }, { - "id": "17a097aa-74ce-4e4e-a678-2c6e9f360252", + "id": "e10dce9e-b66c-4255-aef1-b22b510fab0f", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid ({Tab7Success:value}/{Tab7Total:value})", + "linkLabel": "PaaS ({Tab7Success:value}/{Tab7Total:value})", "subTarget": "tab7", - "preText": "Hybrid", + "preText": "PaaS", "style": "primary" } ] @@ -1494,22 +1494,22 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## Virtual WAN" }, "name": "tab0title" }, { "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": "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": "querytext5" + "name": "querytext27" }, { "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/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", @@ -1558,20 +1558,42 @@ ] } }, - "name": "query5" + "name": "query27" + } + ] + }, + "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" }, { "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": "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": "querytext6" + "name": "querytext9" }, { "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/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", @@ -1620,20 +1642,20 @@ ] } }, - "name": "query6" + "name": "query9" }, { "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": "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": "querytext7" + "name": "querytext10" }, { "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/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", @@ -1682,20 +1704,20 @@ ] } }, - "name": "query7" + "name": "query10" }, { "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": "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": "querytext8" + "name": "querytext11" }, { "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/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", @@ -1744,42 +1766,20 @@ ] } }, - "name": "query8" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## IP plan" - }, - "name": "tab1title" + "name": "query11" }, { "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": "querytext14" + "name": "querytext12" }, { "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", @@ -1828,20 +1828,20 @@ ] } }, - "name": "query14" + "name": "query12" }, { "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": "querytext15" + "name": "querytext13" }, { "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", @@ -1890,7 +1890,7 @@ ] } }, - "name": "query15" + "name": "query13" } ] }, @@ -1910,22 +1910,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Hub and spoke" }, "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": "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": "querytext22" + "name": "querytext5" }, { "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 == '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", @@ -1974,42 +1974,20 @@ ] } }, - "name": "query22" - } - ] - }, - "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" + "name": "query5" }, { "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": "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": "querytext16" + "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 == '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' | 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", @@ -2058,20 +2036,20 @@ ] } }, - "name": "query16" + "name": "query6" }, { "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": "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": "querytext17" + "name": "querytext7" }, { "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/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", @@ -2120,20 +2098,20 @@ ] } }, - "name": "query17" + "name": "query7" }, { "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": "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": "querytext18" + "name": "querytext8" }, { "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' | 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", @@ -2182,82 +2160,42 @@ ] } }, - "name": "query18" - }, + "name": "query8" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab2" + }, + "name": "tab2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ { "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." - }, - "name": "querytext19" - }, - { - "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", - "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" - } - ] - } - } - ] - } + "json": "## IP plan" }, - "name": "query19" + "name": "tab3title" }, { "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": "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": "querytext20" + "name": "querytext14" }, { "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/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", @@ -2306,20 +2244,20 @@ ] } }, - "name": "query20" + "name": "query14" }, { "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": "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": "querytext21" + "name": "querytext15" }, { "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' | 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", @@ -2368,7 +2306,7 @@ ] } }, - "name": "query21" + "name": "query15" } ] }, @@ -2720,22 +2658,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Segmentation" }, "name": "tab5title" }, { "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 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": "querytext27" + "name": "querytext23" }, { "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 == '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", @@ -2784,42 +2722,20 @@ ] } }, - "name": "query27" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab5" - }, - "name": "tab5" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Segmentation" - }, - "name": "tab6title" + "name": "query23" }, { "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": "querytext23" + "name": "querytext24" }, { "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", @@ -2868,20 +2784,20 @@ ] } }, - "name": "query23" + "name": "query24" }, { "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": "querytext24" + "name": "querytext25" }, { "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", @@ -2930,20 +2846,20 @@ ] } }, - "name": "query24" + "name": "query25" }, { "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": "querytext25" + "name": "querytext26" }, { "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", @@ -2992,20 +2908,42 @@ ] } }, - "name": "query25" + "name": "query26" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab5" + }, + "name": "tab5" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Internet" + }, + "name": "tab6title" }, { "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 Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext26" + "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,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/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", @@ -3054,42 +2992,82 @@ ] } }, - "name": "query26" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab6" - }, - "name": "tab6" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query16" + }, { "type": 1, "content": { - "json": "## Hybrid" + "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": "tab7title" + "name": "querytext17" + }, + { + "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", + "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": "query17" }, { "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 Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext9" + "name": "querytext18" }, { "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.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", @@ -3138,20 +3116,20 @@ ] } }, - "name": "query9" + "name": "query18" }, { "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": "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": "querytext10" + "name": "querytext19" }, { "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.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", @@ -3200,20 +3178,20 @@ ] } }, - "name": "query10" + "name": "query19" }, { "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 IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext11" + "name": "querytext20" }, { "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.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", @@ -3262,20 +3240,20 @@ ] } }, - "name": "query11" + "name": "query20" }, { "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": "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": "querytext12" + "name": "querytext21" }, { "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/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", @@ -3324,20 +3302,42 @@ ] } }, - "name": "query12" + "name": "query21" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab6" + }, + "name": "tab6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab7title" }, { "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": "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": "querytext22" }, { "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 = 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", @@ -3386,7 +3386,7 @@ ] } }, - "name": "query13" + "name": "query22" } ] }, diff --git a/workbooks/alz_checklist.en_network_counters_template.json b/workbooks/alz_checklist.en_network_counters_template.json index bca662897..4f80e9568 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/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\": \"Query5Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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,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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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,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\": \"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/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\": \"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\": \"Query23Stats\",\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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.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\": \"Query24Stats\",\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\": \"Query24FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query24Stats:$.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\": \"Query25Stats\",\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\": \"Query25FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query25Stats:$.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\": \"Query26Stats\",\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\": \"Query26FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query26Stats:$.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\": \"Query27Stats\",\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\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.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\": \"{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\": \"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\": \"{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\": \"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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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\": \"{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 \"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\": \"{Query16Stats:$.Success}+{Query17Stats:$.Success}+{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\": \"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\": \"{Query16Stats:$.Total}+{Query17Stats:$.Total}+{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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.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\": \"{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.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\": \"{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.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\": \"Tab7Success\",\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}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Total\",\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}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Percent\",\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*{Tab7Success}/{Tab7Total})\"\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\": \"{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query22Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query27Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.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\": \"{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query22Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query27Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.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\": \"6ad79203-5d04-44eb-82ea-b2803bc6aaaa\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"96043720-2da6-41fe-aef0-41ed83a4fe47\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e53bf286-5a18-4556-9773-1289b816afee\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5c17439a-9f1b-4961-b778-b7bea030f9fa\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f4da2b21-2915-4c30-8585-482cc5168b19\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a65a5b87-fb52-484d-88d3-032c381baa19\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"955b94c2-87b3-484b-8c9f-a44ab1129e66\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"17a097aa-74ce-4e4e-a678-2c6e9f360252\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab7Success:value}/{Tab7Total:value})\",\n \"subTarget\": \"tab7\",\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\": \"## 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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"## IP plan\"\n },\n \"name\": \"tab1title\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"## PaaS\"\n },\n \"name\": \"tab2title\"\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\": \"querytext22\"\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\": \"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\": 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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"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,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\": \"query21\"\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\": \"## App delivery\"\n },\n \"name\": \"tab4title\"\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\": 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\": \"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\": 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\": \"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\": 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\": \"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\": 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 \"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\": 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 },\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\": \"querytext27\"\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\": \"query27\"\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\": \"## Segmentation\"\n },\n \"name\": \"tab6title\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\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\": \"tab7title\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab7\"\n },\n \"name\": \"tab7\"\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 | 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\": \"Query5Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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,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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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,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\": \"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/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\": \"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\": \"Query23Stats\",\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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.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\": \"Query24Stats\",\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\": \"Query24FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query24Stats:$.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\": \"Query25Stats\",\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\": \"Query25FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query25Stats:$.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\": \"Query26Stats\",\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\": \"Query26FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query26Stats:$.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\": \"Query27Stats\",\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\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.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\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.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\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.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\": \"{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\": \"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\": \"{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\": \"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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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\": \"{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\": \"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\": \"{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\": \"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\": \"{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.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\": \"{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.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\": \"{Query16Stats:$.Success}+{Query17Stats:$.Success}+{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\": \"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\": \"{Query16Stats:$.Total}+{Query17Stats:$.Total}+{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\": \"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\": \"Tab7Success\",\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\": \"Tab7Total\",\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\": \"Tab7Percent\",\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*{Tab7Success}/{Tab7Total})\"\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\": \"{Query27Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.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\": \"{Query27Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.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\": \"7f5af678-bf5f-414f-85d9-c83cf5e36b91\",\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\": \"bf90ac83-c8ee-43d3-9f2d-16b012c45255\",\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\": \"a5401b49-46e8-4a4f-a975-e1afb0df0128\",\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\": \"86f08cd3-4078-495c-9863-9923e6139d4d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b77ebfcc-e5a7-4db9-8567-9a03e3473f5e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a80b762c-170f-4b03-81dd-3075236c8d5e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"858f7163-8c75-4143-8ec7-08ffaad8cb51\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e10dce9e-b66c-4255-aef1-b22b510fab0f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab7Success:value}/{Tab7Total:value})\",\n \"subTarget\": \"tab7\",\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\": \"## 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\": \"querytext27\"\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\": \"query27\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"## IP plan\"\n },\n \"name\": \"tab3title\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"## App delivery\"\n },\n \"name\": \"tab4title\"\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\": 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\": \"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\": 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\": \"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\": 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\": \"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\": 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 \"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\": 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 },\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\": \"## Segmentation\"\n },\n \"name\": \"tab5title\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"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,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\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\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\": \"tab7title\"\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\": \"querytext22\"\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\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab7\"\n },\n \"name\": \"tab7\"\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 38d7aec82..8211be1c5 100644 --- a/workbooks/alz_checklist.en_network_tabcounters.json +++ b/workbooks/alz_checklist.en_network_tabcounters.json @@ -70,75 +70,75 @@ "style": "tabs", "links": [ { - "id": "570f3927-4f2a-49aa-a6bc-c261c40c3cae", + "id": "415df7c3-bbc7-4927-b2c8-a405288449bc", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "Hybrid", "subTarget": "tab0", - "preText": "PaaS", + "preText": "Hybrid", "style": "primary" }, { - "id": "fffe5561-191f-44ce-be08-2121e0f177d9", + "id": "14e4c164-1d68-4e01-8348-882df4c7690c", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery", + "linkLabel": "Hub and spoke", "subTarget": "tab1", - "preText": "App delivery", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "a74e8f38-fe2c-4b59-96df-12fd2983950b", + "id": "4185ade4-8bfb-41f4-971b-d8ff086b74f6", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "App delivery", "subTarget": "tab2", - "preText": "Internet", + "preText": "App delivery", "style": "primary" }, { - "id": "50c1817e-6d88-40a2-a476-c1614c327bcc", + "id": "d370720f-6b2c-4d8e-9eb9-4c93cda9925d", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Internet", "subTarget": "tab3", - "preText": "IP plan", + "preText": "Internet", "style": "primary" }, { - "id": "896b9ea2-8cd2-493b-986e-e1159c6afd76", + "id": "c6aa52bb-e9e3-4728-996d-8748a3a75177", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Segmentation", "subTarget": "tab4", - "preText": "Virtual WAN", + "preText": "Segmentation", "style": "primary" }, { - "id": "6a5ce29f-4dd7-4a37-8d09-91d97d305700", + "id": "8b0e19f8-292e-4749-a7d6-c4983f55b18e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "PaaS", "subTarget": "tab5", - "preText": "Hub and spoke", + "preText": "PaaS", "style": "primary" }, { - "id": "0659d358-a6a0-43ce-a894-472ef6de466c", + "id": "6c9941b0-d9ad-47c4-b46f-76e14d54a1c2", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "IP plan", "subTarget": "tab6", - "preText": "Hybrid", + "preText": "IP plan", "style": "primary" }, { - "id": "78b3243a-6fb3-4497-8a27-02961a22406b", + "id": "e083aafc-dbcc-420d-9836-a16ccf1a7bbf", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "Virtual WAN", "subTarget": "tab7", - "preText": "Segmentation", + "preText": "Virtual WAN", "style": "primary" } ] @@ -162,9 +162,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22Stats", + "name": "Query9Stats", "type": 1, - "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())", + "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}" ], @@ -178,9 +178,121 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22FullyCompliant", + "name": "Query9FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query9Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query10Stats", + "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": "Query10FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query10Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query11Stats", + "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": "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/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": "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", + "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": "Query13FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -201,7 +313,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" + "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" } } ] @@ -220,7 +332,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" + "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" } } ] @@ -254,7 +366,7 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Hybrid" }, "customWidth": "50", "name": "tab0title" @@ -295,15 +407,15 @@ { "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": "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": "querytext9" }, { "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/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", @@ -352,367 +464,37 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query9" + }, { - "type": 9, + "type": 1, "content": { - "version": "KqlParameterItem/1.0", + "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": "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", "crossComponentResources": [ "{Subscription}" ], - "parameters": [ - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query0Stats", - "type": 1, - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query0FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query1Stats", - "type": 1, - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query1FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query2FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query3Stats", - "type": 1, - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query3FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query4Stats", - "type": 1, - "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())", - "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": "Tab1Success", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab1Total", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab1Percent", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "round(100*{Tab1Success}/{Tab1Total})" - } - } - ] - } - ], - "style": "pills", - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - "name": "TabInvisibleParameters" - }, - { - "type": 1, - "content": { - "json": "## App delivery" - }, - "customWidth": "50", - "name": "tab1title" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab1Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful 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 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." - }, - "name": "querytext0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "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", - "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": "query0" - }, - { - "type": 1, - "content": { - "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." - }, - "name": "querytext1" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "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", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } }, { "columnMatch": "compliant", @@ -744,20 +526,20 @@ ] } }, - "name": "query1" + "name": "query10" }, { "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": "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": "querytext2" + "name": "querytext11" }, { "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/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", @@ -806,20 +588,20 @@ ] } }, - "name": "query2" + "name": "query11" }, { "type": 1, "content": { - "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." + "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": "querytext3" + "name": "querytext12" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "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", + "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", @@ -868,20 +650,20 @@ ] } }, - "name": "query3" + "name": "query12" }, { "type": 1, "content": { - "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." + "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": "querytext4" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "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", + "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", @@ -930,16 +712,16 @@ ] } }, - "name": "query4" + "name": "query13" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab1" + "value": "tab0" }, - "name": "tab1" + "name": "tab0" }, { "type": 12, @@ -958,65 +740,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query16Stats", - "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": "Query16FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query17Stats", - "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": "Query17FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query18Stats", + "name": "Query5Stats", "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 == '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}" ], @@ -1030,9 +756,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query18FullyCompliant", + "name": "Query5FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1042,9 +768,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query19Stats", + "name": "Query6Stats", "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' | 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}" ], @@ -1058,9 +784,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query19FullyCompliant", + "name": "Query6FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1070,9 +796,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query20Stats", + "name": "Query7Stats", "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/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}" ], @@ -1086,9 +812,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query20FullyCompliant", + "name": "Query7FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1098,9 +824,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21Stats", + "name": "Query8Stats", "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' | 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}" ], @@ -1114,9 +840,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21FullyCompliant", + "name": "Query8FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1126,7 +852,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Success", + "name": "Tab1Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1137,7 +863,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -1145,7 +871,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Total", + "name": "Tab1Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1156,7 +882,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -1164,7 +890,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Percent", + "name": "Tab1Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1175,7 +901,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab2Success}/{Tab2Total})" + "resultVal": "round(100*{Tab1Success}/{Tab1Total})" } } ] @@ -1190,16 +916,16 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Hub and spoke" }, "customWidth": "50", - "name": "tab2title" + "name": "tab1title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab2Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab1Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -1231,139 +957,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." - }, - "name": "querytext16" - }, - { - "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", - "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" - }, - { - "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." - }, - "name": "querytext17" - }, - { - "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", - "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": "query17" - }, - { - "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": "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": "querytext18" + "name": "querytext5" }, { "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,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", @@ -1412,20 +1014,20 @@ ] } }, - "name": "query18" + "name": "query5" }, { "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": "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": "querytext19" + "name": "querytext6" }, { "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' | 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", @@ -1474,20 +1076,20 @@ ] } }, - "name": "query19" + "name": "query6" }, { "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": "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": "querytext20" + "name": "querytext7" }, { "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/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", @@ -1536,20 +1138,20 @@ ] } }, - "name": "query20" + "name": "query7" }, { "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": "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": "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,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' | 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", @@ -1598,16 +1200,16 @@ ] } }, - "name": "query21" + "name": "query8" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab2" + "value": "tab1" }, - "name": "tab2" + "name": "tab1" }, { "type": 12, @@ -1626,9 +1228,93 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14Stats", + "name": "Query0Stats", + "type": 1, + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query0FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query1Stats", + "type": 1, + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query1FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query2FullyCompliant", "type": 1, - "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())", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query3Stats", + "type": 1, + "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())", "crossComponentResources": [ "{Subscription}" ], @@ -1642,9 +1328,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14FullyCompliant", + "name": "Query3FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1654,9 +1340,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15Stats", + "name": "Query4Stats", "type": 1, - "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())", + "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())", "crossComponentResources": [ "{Subscription}" ], @@ -1670,9 +1356,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15FullyCompliant", + "name": "Query4FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1682,7 +1368,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Success", + "name": "Tab2Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1693,7 +1379,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -1701,7 +1387,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Total", + "name": "Tab2Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1712,7 +1398,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" } } ] @@ -1720,7 +1406,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Percent", + "name": "Tab2Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1731,7 +1417,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab3Success}/{Tab3Total})" + "resultVal": "round(100*{Tab2Success}/{Tab2Total})" } } ] @@ -1746,16 +1432,16 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## App delivery" }, "customWidth": "50", - "name": "tab3title" + "name": "tab2title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab2Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -1787,15 +1473,15 @@ { "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": "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." }, - "name": "querytext14" + "name": "querytext0" }, { "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/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", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1844,20 +1530,20 @@ ] } }, - "name": "query14" + "name": "query0" }, { "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": "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." }, - "name": "querytext15" + "name": "querytext1" }, { "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/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1906,176 +1592,144 @@ ] } }, - "name": "query15" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query1" + }, { - "type": 9, + "type": 1, "content": { - "version": "KqlParameterItem/1.0", + "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." + }, + "name": "querytext2" + }, + { + "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", "crossComponentResources": [ "{Subscription}" ], - "parameters": [ - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query27Stats", - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query27FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query27Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab4Success", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query27Stats:$.Success}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab4Total", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query27Stats:$.Total}" + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab4Percent", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "round(100*{Tab4Success}/{Tab4Total})" - } + { + "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" + } + ] } - ] - } - ], - "style": "pills", - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" + } + ] + } }, - "name": "TabInvisibleParameters" + "name": "query2" }, { "type": 1, "content": { - "json": "## Virtual WAN" + "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." }, - "customWidth": "50", - "name": "tab4title" + "name": "querytext3" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", - "size": 3, - "queryType": 8, - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 4, - "formatOptions": { - "min": 0, - "max": 100, - "palette": "redGreen" + "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } }, - "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" + } + ] } } - }, - "subtitleContent": { - "columnMatch": "Column2" - }, - "showBorder": true + ] } }, - "customWidth": "50", - "name": "TabPercentTile" + "name": "query3" }, { "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 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." }, - "name": "querytext27" + "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/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", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2124,16 +1778,16 @@ ] } }, - "name": "query27" + "name": "query4" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab2" }, - "name": "tab4" + "name": "tab2" }, { "type": 12, @@ -2152,9 +1806,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5Stats", + "name": "Query16Stats", "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/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}" ], @@ -2168,9 +1822,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5FullyCompliant", + "name": "Query16FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2180,9 +1834,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6Stats", + "name": "Query17Stats", "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.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}" ], @@ -2196,9 +1850,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6FullyCompliant", + "name": "Query17FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2208,9 +1862,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7Stats", + "name": "Query18Stats", "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.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}" ], @@ -2224,9 +1878,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7FullyCompliant", + "name": "Query18FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2236,9 +1890,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8Stats", + "name": "Query19Stats", "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/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}" ], @@ -2252,9 +1906,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8FullyCompliant", + "name": "Query19FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2264,7 +1918,63 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Success", + "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())", + "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", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query21FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab3Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2275,7 +1985,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -2283,7 +1993,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Total", + "name": "Tab3Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2294,7 +2004,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -2302,7 +2012,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Percent", + "name": "Tab3Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2313,71 +2023,195 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab5Success}/{Tab5Total})" + "resultVal": "round(100*{Tab3Success}/{Tab3Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + "name": "TabInvisibleParameters" + }, + { + "type": 1, + "content": { + "json": "## Internet" + }, + "customWidth": "50", + "name": "tab3title" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful 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": "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": "querytext16" + }, + { + "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] - } - ], - "style": "pills", - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" + }, + { + "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": "TabInvisibleParameters" + "name": "query16" }, { "type": 1, "content": { - "json": "## Hub and spoke" + "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." }, - "customWidth": "50", - "name": "tab5title" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", - "size": 3, - "queryType": 8, - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 4, - "formatOptions": { - "min": 0, - "max": 100, - "palette": "redGreen" + "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", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } }, - "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" + } + ] } } - }, - "subtitleContent": { - "columnMatch": "Column2" - }, - "showBorder": true + ] } }, - "customWidth": "50", - "name": "TabPercentTile" + "name": "query17" }, { "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 Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext5" + "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 == '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/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", @@ -2426,20 +2260,20 @@ ] } }, - "name": "query5" + "name": "query18" }, { "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": "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": "querytext19" }, { "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.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", @@ -2488,20 +2322,20 @@ ] } }, - "name": "query6" + "name": "query19" }, { "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": "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": "querytext20" }, { "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.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", @@ -2550,20 +2384,20 @@ ] } }, - "name": "query7" + "name": "query20" }, { "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": "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": "querytext21" }, { "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/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", @@ -2612,16 +2446,16 @@ ] } }, - "name": "query8" + "name": "query21" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab3" }, - "name": "tab5" + "name": "tab3" }, { "type": 12, @@ -2640,37 +2474,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query9Stats", - "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": "Query9FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query9Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query10Stats", + "name": "Query23Stats", "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())", + "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}" ], @@ -2684,9 +2490,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query10FullyCompliant", + "name": "Query23FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query10Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2696,9 +2502,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11Stats", + "name": "Query24Stats", "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' | 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}" ], @@ -2712,9 +2518,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11FullyCompliant", + "name": "Query24FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2724,9 +2530,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query12Stats", + "name": "Query25Stats", "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/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}" ], @@ -2740,9 +2546,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query12FullyCompliant", + "name": "Query25FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query12Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2752,9 +2558,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query13Stats", + "name": "Query26Stats", "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' | 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}" ], @@ -2768,9 +2574,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query13FullyCompliant", + "name": "Query26FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query26Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2780,7 +2586,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Success", + "name": "Tab4Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2791,7 +2597,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" } } ] @@ -2799,7 +2605,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Total", + "name": "Tab4Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2810,7 +2616,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" } } ] @@ -2818,7 +2624,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Percent", + "name": "Tab4Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2829,7 +2635,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab6Success}/{Tab6Total})" + "resultVal": "round(100*{Tab4Success}/{Tab4Total})" } } ] @@ -2844,16 +2650,16 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## Segmentation" }, "customWidth": "50", - "name": "tab6title" + "name": "tab4title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab6Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -2863,99 +2669,37 @@ "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": "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", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } + "max": 100, + "palette": "redGreen" }, - { - "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" - } - ] + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true } }, - "name": "query9" + "customWidth": "50", + "name": "TabPercentTile" }, { "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 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": "querytext10" + "name": "querytext23" }, { "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 == '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", @@ -3004,20 +2748,20 @@ ] } }, - "name": "query10" + "name": "query23" }, { "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 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": "querytext11" + "name": "querytext24" }, { "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 == '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", @@ -3066,20 +2810,20 @@ ] } }, - "name": "query11" + "name": "query24" }, { "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": "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": "querytext12" + "name": "querytext25" }, { "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/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", @@ -3128,20 +2872,20 @@ ] } }, - "name": "query12" + "name": "query25" }, { "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": "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": "querytext13" + "name": "querytext26" }, { "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,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", @@ -3190,16 +2934,16 @@ ] } }, - "name": "query13" + "name": "query26" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab6" + "value": "tab4" }, - "name": "tab6" + "name": "tab4" }, { "type": 12, @@ -3218,9 +2962,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23Stats", + "name": "Query22Stats", "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())", + "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())", "crossComponentResources": [ "{Subscription}" ], @@ -3234,9 +2978,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23FullyCompliant", + "name": "Query22FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3246,37 +2990,199 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query24Stats", + "name": "Tab5Success", "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" + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query22Stats:$.Success}" + } + } + ] }, { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query24FullyCompliant", + "name": "Tab5Total", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, - "queryType": 8 + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query22Stats:$.Total}" + } + } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab5Percent", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "round(100*{Tab5Success}/{Tab5Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + "name": "TabInvisibleParameters" + }, + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "customWidth": "50", + "name": "tab5title" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful 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": "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": "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 = 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", + "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": "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": "Query25Stats", + "name": "Query14Stats", "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())", + "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())", "crossComponentResources": [ "{Subscription}" ], @@ -3290,9 +3196,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query25FullyCompliant", + "name": "Query14FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3302,9 +3208,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query26Stats", + "name": "Query15Stats", "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/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())", "crossComponentResources": [ "{Subscription}" ], @@ -3318,9 +3224,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query26FullyCompliant", + "name": "Query15FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query26Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3330,7 +3236,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab7Success", + "name": "Tab6Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3341,7 +3247,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" } } ] @@ -3349,7 +3255,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab7Total", + "name": "Tab6Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3360,7 +3266,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" } } ] @@ -3368,7 +3274,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab7Percent", + "name": "Tab6Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3379,7 +3285,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab7Success}/{Tab7Total})" + "resultVal": "round(100*{Tab6Success}/{Tab6Total})" } } ] @@ -3394,16 +3300,16 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## IP plan" }, "customWidth": "50", - "name": "tab7title" + "name": "tab6title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab7Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab6Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -3435,15 +3341,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." + "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": "querytext23" + "name": "querytext14" }, { "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' | 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", @@ -3492,20 +3398,20 @@ ] } }, - "name": "query23" + "name": "query14" }, { "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": "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": "querytext24" + "name": "querytext15" }, { "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/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", @@ -3554,82 +3460,176 @@ ] } }, - "name": "query24" + "name": "query15" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab6" + }, + "name": "tab6" + }, + { + "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": "Query27Stats", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query27FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query27Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab7Success", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query27Stats:$.Success}" + } + } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab7Total", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query27Stats:$.Total}" + } + } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab7Percent", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "round(100*{Tab7Success}/{Tab7Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + "name": "TabInvisibleParameters" }, { "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": "## Virtual WAN" }, - "name": "querytext25" + "customWidth": "50", + "name": "tab7title" }, { "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" - } - } + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab7Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "size": 3, + "queryType": 8, + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 4, + "formatOptions": { + "min": 0, + "max": 100, + "palette": "redGreen" }, - { - "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" - } - ] + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true } }, - "name": "query25" + "customWidth": "50", + "name": "TabPercentTile" }, { "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": "querytext26" + "name": "querytext27" }, { "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", @@ -3678,7 +3678,7 @@ ] } }, - "name": "query26" + "name": "query27" } ] }, diff --git a/workbooks/alz_checklist.en_network_tabcounters_template.json b/workbooks/alz_checklist.en_network_tabcounters_template.json index 89e64609c..4436465d7 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\": \"570f3927-4f2a-49aa-a6bc-c261c40c3cae\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab0\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"fffe5561-191f-44ce-be08-2121e0f177d9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab1\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a74e8f38-fe2c-4b59-96df-12fd2983950b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"50c1817e-6d88-40a2-a476-c1614c327bcc\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"896b9ea2-8cd2-493b-986e-e1159c6afd76\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6a5ce29f-4dd7-4a37-8d09-91d97d305700\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0659d358-a6a0-43ce-a894-472ef6de466c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"78b3243a-6fb3-4497-8a27-02961a22406b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Segmentation\",\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\": \"Query22Stats\",\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\": \"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 \"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\": \"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 succesful 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\": \"querytext22\"\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\": \"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\": 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/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\": \"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}+{Query4Stats:$.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}+{Query4Stats:$.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\": \"## App delivery\"\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 succesful 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 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\": 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\": \"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\": 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\": \"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\": 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\": \"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\": 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 \"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\": 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 },\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\": \"Query16Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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,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\": \"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\": \"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\": \"{Query16Stats:$.Success}+{Query17Stats:$.Success}+{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\": \"{Query16Stats:$.Total}+{Query17Stats:$.Total}+{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 \"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 succesful 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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"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,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\": \"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\": 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\": \"Query14Stats\",\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\": \"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/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\": \"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\": \"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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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\": \"## IP plan\"\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 succesful 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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"Query27Stats\",\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\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.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 succesful 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\": \"querytext27\"\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\": \"query27\"\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\": \"Query5Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"## Hub and spoke\"\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 succesful 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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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\": \"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}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.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}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.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 succesful 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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\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\": \"Query23Stats\",\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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.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\": \"Query24Stats\",\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\": \"Query24FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query24Stats:$.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\": \"Query25Stats\",\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\": \"Query25FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query25Stats:$.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\": \"Query26Stats\",\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\": \"Query26FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query26Stats:$.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\": \"Tab7Success\",\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\": \"{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Total\",\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\": \"{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Percent\",\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*{Tab7Success}/{Tab7Total})\"\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\": \"tab7title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab7Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful 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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab7\"\n },\n \"name\": \"tab7\"\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\": \"415df7c3-bbc7-4927-b2c8-a405288449bc\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"14e4c164-1d68-4e01-8348-882df4c7690c\",\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\": \"4185ade4-8bfb-41f4-971b-d8ff086b74f6\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab2\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d370720f-6b2c-4d8e-9eb9-4c93cda9925d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"c6aa52bb-e9e3-4728-996d-8748a3a75177\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8b0e19f8-292e-4749-a7d6-c4983f55b18e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6c9941b0-d9ad-47c4-b46f-76e14d54a1c2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab6\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e083aafc-dbcc-420d-9836-a16ccf1a7bbf\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Virtual WAN\",\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\": \"Query9Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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\": \"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\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.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\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.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\": \"## Hybrid\"\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 succesful 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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\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\": \"Query5Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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\": \"{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\": \"{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\": \"## 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 succesful 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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"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\": \"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\": \"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}+{Query4Stats:$.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}+{Query4Stats:$.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\": \"## App delivery\"\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 succesful 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 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\": 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\": \"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\": 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\": \"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\": 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\": \"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\": 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 \"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\": 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 },\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\": \"Query16Stats\",\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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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,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\": \"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\": \"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\": \"{Query16Stats:$.Success}+{Query17Stats:$.Success}+{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\": \"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\": \"{Query16Stats:$.Total}+{Query17Stats:$.Total}+{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\": \"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\": \"## Internet\"\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 succesful 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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"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,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\": \"query21\"\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\": \"Query23Stats\",\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\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.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\": \"Query24Stats\",\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\": \"Query24FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query24Stats:$.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\": \"Query25Stats\",\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\": \"Query25FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query25Stats:$.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\": \"Query26Stats\",\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\": \"Query26FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query26Stats:$.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\": \"{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.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\": \"{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.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\": \"## Segmentation\"\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 succesful 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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"Query22Stats\",\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\": \"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\": \"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\": \"{Query22Stats:$.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\": \"{Query22Stats:$.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\": \"## PaaS\"\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 succesful 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\": \"querytext22\"\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\": \"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\": 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\": \"Query14Stats\",\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\": \"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/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\": \"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\": \"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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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 succesful 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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\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\": \"Query27Stats\",\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\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.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\": \"Tab7Success\",\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\": \"{Query27Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Total\",\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\": \"{Query27Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Percent\",\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*{Tab7Success}/{Tab7Total})\"\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\": \"tab7title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab7Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful 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\": \"querytext27\"\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\": \"query27\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab7\"\n },\n \"name\": \"tab7\"\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 982567430..6a1cdbb41 100644 --- a/workbooks/alz_checklist.en_network_workbook.json +++ b/workbooks/alz_checklist.en_network_workbook.json @@ -70,43 +70,43 @@ "style": "tabs", "links": [ { - "id": "60e475be-d7fe-4c9c-9448-4fdcc1f8c406", + "id": "8c90b607-670f-41ac-84c7-95a84f5904d0", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Segmentation", "subTarget": "tab0", - "preText": "Virtual WAN", + "preText": "Segmentation", "style": "primary" }, { - "id": "0be12da6-1d30-4782-be46-43de817d71f2", + "id": "706eb56e-6e9e-460a-ab31-ebc84b79c875", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "IP plan", "subTarget": "tab1", - "preText": "Hybrid", + "preText": "IP plan", "style": "primary" }, { - "id": "735c75d1-0dc6-4bee-b316-6409675f7e0a", + "id": "0ebfe6d9-3a04-4c69-95d7-926be81c6e04", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "Internet", "subTarget": "tab2", - "preText": "Segmentation", + "preText": "Internet", "style": "primary" }, { - "id": "22b8dba5-ba0b-4a76-887b-dcd28193e0dc", + "id": "2f60de2b-b165-421c-a6ec-962abb1eacd6", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Virtual WAN", "subTarget": "tab3", - "preText": "IP plan", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "f42dc4cf-5e08-4d27-8899-4d5afa11aaa9", + "id": "135a5550-743d-45f7-94f6-e86d005a9584", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Hub and spoke", @@ -115,7 +115,7 @@ "style": "primary" }, { - "id": "e43ae6f9-315c-4da3-8dba-73b9d7354a6f", + "id": "42b85462-0574-4137-af7d-a25de337251f", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "PaaS", @@ -124,16 +124,16 @@ "style": "primary" }, { - "id": "a576ae67-2ed7-4714-bf5d-32ddd47365c0", + "id": "20338640-941f-45a0-bfe9-d1ee7de87be2", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "Hybrid", "subTarget": "tab6", - "preText": "Internet", + "preText": "Hybrid", "style": "primary" }, { - "id": "c4d281f2-9e50-4e52-b0a2-09828d074550", + "id": "2083355f-1254-407d-8d3a-4aa95d44efd1", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "App delivery", @@ -154,22 +154,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Segmentation" }, "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 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": "querytext27" + "name": "querytext23" }, { "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 == '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", @@ -218,42 +218,20 @@ ] } }, - "name": "query27" - } - ] - }, - "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": "query23" }, { "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 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": "querytext9" + "name": "querytext24" }, { "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' | 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", @@ -302,20 +280,20 @@ ] } }, - "name": "query9" + "name": "query24" }, { "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": "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": "querytext10" + "name": "querytext25" }, { "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/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", @@ -364,20 +342,20 @@ ] } }, - "name": "query10" + "name": "query25" }, { "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": "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": "querytext11" + "name": "querytext26" }, { "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,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", @@ -426,20 +404,42 @@ ] } }, - "name": "query11" + "name": "query26" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab0" + }, + "name": "tab0" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## IP plan" + }, + "name": "tab1title" }, { "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 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": "querytext12" + "name": "querytext14" }, { "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/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", @@ -488,20 +488,20 @@ ] } }, - "name": "query12" + "name": "query14" }, { "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": "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": "querytext13" + "name": "querytext15" }, { "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' | 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", @@ -550,7 +550,7 @@ ] } }, - "name": "query13" + "name": "query15" } ] }, @@ -570,22 +570,22 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## Internet" }, "name": "tab2title" }, { "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 Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext23" + "name": "querytext16" }, { "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 == '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", @@ -634,20 +634,20 @@ ] } }, - "name": "query23" + "name": "query16" }, { "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": "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": "querytext24" + "name": "querytext17" }, { "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/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", @@ -696,20 +696,20 @@ ] } }, - "name": "query24" + "name": "query17" }, { "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": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext25" + "name": "querytext18" }, { "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/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", @@ -758,20 +758,20 @@ ] } }, - "name": "query25" + "name": "query18" }, { "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": "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": "querytext26" + "name": "querytext19" }, { "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/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", @@ -820,42 +820,20 @@ ] } }, - "name": "query26" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab2" - }, - "name": "tab2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## IP plan" - }, - "name": "tab3title" + "name": "query19" }, { "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 IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext14" + "name": "querytext20" }, { "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.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", @@ -904,20 +882,20 @@ ] } }, - "name": "query14" + "name": "query20" }, { "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": "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": "querytext15" + "name": "querytext21" }, { "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/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", @@ -966,16 +944,16 @@ ] } }, - "name": "query15" + "name": "query21" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab3" + "value": "tab2" }, - "name": "tab3" + "name": "tab2" }, { "type": 12, @@ -986,22 +964,22 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## Virtual WAN" }, - "name": "tab4title" + "name": "tab3title" }, { "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": "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": "querytext5" + "name": "querytext27" }, { "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/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", @@ -1050,20 +1028,42 @@ ] } }, - "name": "query5" + "name": "query27" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab3" + }, + "name": "tab3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Hub and spoke" + }, + "name": "tab4title" }, { "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": "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": "querytext6" + "name": "querytext5" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1112,20 +1112,20 @@ ] } }, - "name": "query6" + "name": "query5" }, { "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": "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": "querytext7" + "name": "querytext6" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1174,20 +1174,20 @@ ] } }, - "name": "query7" + "name": "query6" }, { "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": "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": "querytext8" + "name": "querytext7" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1236,42 +1236,20 @@ ] } }, - "name": "query8" - } - ] - }, - "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": "query7" }, { "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 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": "querytext22" + "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 = 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' | 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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1320,16 +1298,16 @@ ] } }, - "name": "query22" + "name": "query8" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab4" }, - "name": "tab5" + "name": "tab4" }, { "type": 12, @@ -1340,22 +1318,22 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## PaaS" }, - "name": "tab6title" + "name": "tab5title" }, { "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": "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": "querytext22" }, { "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,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", @@ -1404,20 +1382,42 @@ ] } }, - "name": "query16" + "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": "## Hybrid" + }, + "name": "tab6title" }, { "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 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": "querytext17" + "name": "querytext9" }, { "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/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", @@ -1466,20 +1466,20 @@ ] } }, - "name": "query17" + "name": "query9" }, { "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": "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": "querytext10" }, { "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/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", @@ -1528,20 +1528,20 @@ ] } }, - "name": "query18" + "name": "query10" }, { "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": "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": "querytext11" }, { "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/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", @@ -1590,20 +1590,20 @@ ] } }, - "name": "query19" + "name": "query11" }, { "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": "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": "querytext12" }, { "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/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", @@ -1652,20 +1652,20 @@ ] } }, - "name": "query20" + "name": "query12" }, { "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": "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": "querytext13" }, { "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/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", @@ -1714,7 +1714,7 @@ ] } }, - "name": "query21" + "name": "query13" } ] }, diff --git a/workbooks/alz_checklist.en_network_workbook_template.json b/workbooks/alz_checklist.en_network_workbook_template.json index 6cb5e054d..b27a8fc62 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\": \"60e475be-d7fe-4c9c-9448-4fdcc1f8c406\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0be12da6-1d30-4782-be46-43de817d71f2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"735c75d1-0dc6-4bee-b316-6409675f7e0a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"22b8dba5-ba0b-4a76-887b-dcd28193e0dc\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f42dc4cf-5e08-4d27-8899-4d5afa11aaa9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e43ae6f9-315c-4da3-8dba-73b9d7354a6f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a576ae67-2ed7-4714-bf5d-32ddd47365c0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"c4d281f2-9e50-4e52-b0a2-09828d074550\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab7\",\n \"preText\": \"App delivery\",\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\": \"querytext27\"\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\": \"query27\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"## IP plan\"\n },\n \"name\": \"tab3title\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"## Hub and spoke\"\n },\n \"name\": \"tab4title\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext22\"\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\": \"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\": \"## 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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"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,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\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\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\": \"## App delivery\"\n },\n \"name\": \"tab7title\"\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\": \"tab7\"\n },\n \"name\": \"tab7\"\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\": \"8c90b607-670f-41ac-84c7-95a84f5904d0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"706eb56e-6e9e-460a-ab31-ebc84b79c875\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab1\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0ebfe6d9-3a04-4c69-95d7-926be81c6e04\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2f60de2b-b165-421c-a6ec-962abb1eacd6\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"135a5550-743d-45f7-94f6-e86d005a9584\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"42b85462-0574-4137-af7d-a25de337251f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"20338640-941f-45a0-bfe9-d1ee7de87be2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2083355f-1254-407d-8d3a-4aa95d44efd1\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab7\",\n \"preText\": \"App delivery\",\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\": \"## Segmentation\"\n },\n \"name\": \"tab0title\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"## IP plan\"\n },\n \"name\": \"tab1title\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"## Internet\"\n },\n \"name\": \"tab2title\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"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,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\": \"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\": \"querytext27\"\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\": \"query27\"\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\": \"## Hub and spoke\"\n },\n \"name\": \"tab4title\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext22\"\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\": \"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\": \"## 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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\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\": \"## App delivery\"\n },\n \"name\": \"tab7title\"\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\": \"tab7\"\n },\n \"name\": \"tab7\"\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')]"