From d94eeb0ac6753bc63c6dbe56ac80754beba26de4 Mon Sep 17 00:00:00 2001 From: brsteph Date: Thu, 14 Sep 2023 17:36:06 +0000 Subject: [PATCH] [create-pull-request] automated change --- checklists/alz_checklist.en.json | 5212 ++++++++--------- checklists/alz_checklist.es.json | 366 +- checklists/alz_checklist.ja.json | 366 +- checklists/alz_checklist.ko.json | 366 +- checklists/alz_checklist.pt.json | 366 +- spreadsheet/macrofree/alz_checklist.en.xlsx | Bin 47732 -> 47967 bytes spreadsheet/macrofree/alz_checklist.es.xlsx | Bin 49901 -> 50168 bytes spreadsheet/macrofree/alz_checklist.ja.xlsx | Bin 54917 -> 55193 bytes spreadsheet/macrofree/alz_checklist.ko.xlsx | Bin 53248 -> 53501 bytes spreadsheet/macrofree/alz_checklist.pt.xlsx | Bin 50086 -> 50364 bytes .../alz_checklist.en_counters_workbook.json | 8 +- ...ecklist.en_counters_workbook_template.json | 2 +- .../alz_checklist.en_network_counters.json | 596 +- ...hecklist.en_network_counters_template.json | 2 +- .../alz_checklist.en_network_tabcounters.json | 1806 +++--- ...klist.en_network_tabcounters_template.json | 2 +- .../alz_checklist.en_network_workbook.json | 476 +- ...hecklist.en_network_workbook_template.json | 2 +- workbooks/alz_checklist.en_workbook.json | 8 +- .../alz_checklist.en_workbook_template.json | 2 +- 20 files changed, 5318 insertions(+), 4262 deletions(-) diff --git a/checklists/alz_checklist.en.json b/checklists/alz_checklist.en.json index fcca4b333..fc21a8851 100644 --- a/checklists/alz_checklist.en.json +++ b/checklists/alz_checklist.en.json @@ -1,2608 +1,2608 @@ { - "items": [ - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Azure AD 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", - "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", - "id": "A01.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Azure AD Tenants", - "text": "Ensure you have a Multi-Tenant Automation approach to managing your Azure AD Tenants", - "waf": "Operations", - "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", - "id": "A01.02", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Azure AD Tenants", - "text": "Leverage Azure Lighthouse for Multi-Tenant Management", - "waf": "Operations", - "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", - "id": "A01.03", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Cloud Solution Provider", - "text": "Ensure that Azure Lighthouse is used for administering the tenant by partner", - "waf": "Cost", - "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", - "id": "A02.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Cloud Solution Provider", - "text": "Discuss support request and escalation process with CSP partner", - "waf": "Cost", - "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", - "id": "A02.02", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Cloud Solution Provider", - "text": "Setup Cost Reporting and Views with Azure Cost Management", - "waf": "Cost", - "guid": "32952499-58c8-4e6f-ada5-972e67893d55", - "id": "A02.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Enterprise Agreement", - "text": "Configure Notification Contacts to a group mailbox", - "waf": "Cost", - "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", - "id": "A03.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Enterprise Agreement", - "text": "Use departments and accounts to map your organization's structure to your enrollment hierarchy can help with separating billing.", - "waf": "Cost", - "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", - "id": "A03.02", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Enterprise Agreement", - "text": "Ensure that Accounts are configured to be of the type 'Work and School Account'", - "waf": "Security", - "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", - "id": "A03.03", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Enterprise Agreement", - "text": "Enable both DA View Charges and AO View Charges on your EA Enrollments to allowers users with the correct perms review Cost and Billing Data.", - "waf": "Security", - "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", - "id": "A03.04", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Enterprise Agreement", - "text": "Make use of Enterprise Dev/Test Subscriptions to reduce costs for non-production workloads", - "waf": "Cost", - "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", - "id": "A03.05", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Enterprise Agreement", - "text": "Periodically audit the role assignments to review who has access to your Enterprise Agreement Enrollment", - "waf": "Cost", - "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", - "id": "A03.06", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Microsoft Cloud Agreement", - "text": "Configure Agreement billing account notification contact email", - "waf": "Cost", - "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", - "id": "A04.01", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Microsoft Cloud Agreement", - "text": "Use Billing Profiles and Invoice sections to structure your agreements billing for effective cost management", - "waf": "Cost", - "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", - "id": "A04.02", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Microsoft Cloud Agreement", - "text": "Make use of Azure Plan to reduce costs for non-production workloads", - "waf": "Cost", - "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", - "id": "A04.03", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" - }, - { - "category": "Azure Billing and Active Directory Tenant", - "subcategory": "Microsoft Cloud Agreement", - "text": "Periodically audit the agreement billing RBAC role assignments to review who has access to your MCA billing account", - "waf": "Cost", - "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", - "id": "A04.04", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Leverage Azure Policy strategically, define controls for your environment, using Policy Initiatives to group related policies.", - "waf": "Security", - "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", - "id": "B01.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Identify required Azure tags and use the 'append' policy mode to enforce usage.", - "waf": "Security", - "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", - "id": "B01.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments.", - "waf": "Security", - "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", - "id": "B01.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Establish Azure Policy definitions at the top-level root management group so that they can be assigned at inherited scopes", - "waf": "Security", - "guid": "223ace8c-b123-408c-a501-7f154e3ab369", - "id": "B01.04", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required.", - "waf": "Security", - "guid": "3829e7e3-1618-4368-9a04-77a209945bda", - "id": "B01.05", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Use Azure Policy to control which services users can provision at the subscription/management group level", - "waf": "Security", - "guid": "43334f24-9116-4341-a2ba-527526944008", - "id": "B01.06", - "severity": "Low", - "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Use built-in policies where possible to minimize operational overhead.", - "waf": "Security", - "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", - "id": "B01.07", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Governance", - "subcategory": "Governance", - "text": "Assign the built-in Resource Policy Contributor role at a particular scope to enable application-level governance.", - "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.", - "waf": "Security", - "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", - "id": "B01.08", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy" - }, - { - "category": "Governance", - "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", - "guid": "19048384-5c98-46cb-8913-156a12476e49", - "id": "B01.09", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Governance", - "subcategory": "Optimize your cloud investment", - "text": "Consider using automation tags to start/stop VM's in your environment to save on cost.", - "waf": "Security", - "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", - "id": "B02.01", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config" - }, - { - "category": "Governance", - "subcategory": "Optimize your cloud investment", - "text": "Configure 'Actual' and 'Forecasted' Budget Alerts.", - "waf": "Cost", - "guid": "29fd366b-a180-452b-9bd7-954b7700c667", - "id": "B02.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json" - }, - { - "category": "Identity and Access Management", - "subcategory": "Active Directory and Hybrid Identity", - "text": "Use managed identities instead of service principals for authentication to Azure services", - "waf": "Security", - "guid": "4348bf81-7573-4512-8f46-9061cc198fea", - "id": "C01.01", - "severity": "High", - "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator" - }, - { - "category": "Identity and Access Management", - "subcategory": "Azure AD", - "text": "When deploying an AD Connect VM, consider having a staging sever for high availability / Disaster recovery", - "waf": "Reliability", - "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", - "id": "C02.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Implement an emergency access or break-glass accounts to prevent tenant-wide account lockout", - "waf": "Security", - "guid": "984a859c-773e-47d2-9162-3a765a917e1f", - "id": "C03.01", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Integrate Azure AD 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", - "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", - "id": "C03.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Enforce a RBAC model that aligns to your cloud operating model. Scope and Assign across Management Groups and Subscriptions.", - "waf": "Security", - "guid": "348ef254-c27d-442e-abba-c7571559ab91", - "id": "C03.03", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/role-based-access-control/overview" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Enforce Azure AD conditional-access policies for any user with rights to Azure environments", - "waf": "Security", - "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", - "id": "C03.04", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", - "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Enforce multi-factor authentication for any user with rights to the Azure environments", - "waf": "Security", - "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", - "id": "C03.05", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", - "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Enforce centralized and delegated responsibilities to manage resources deployed inside the landing zone, based on role and security requirements", - "waf": "Security", - "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", - "id": "C03.06", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Enforce Azure AD Privileged Identity Management (PIM) to establish zero standing access and least privilege", - "waf": "Security", - "guid": "14658d35-58fd-4772-99b8-21112df27ee4", - "id": "C03.07", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Only use the authentication type Work or school account for all account types. Avoid using the Microsoft account", - "waf": "Security", - "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", - "id": "C03.08", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts" - }, - { - "category": "Identity and Access Management", - "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.", - "waf": "Security", - "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", - "id": "C03.09", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", - "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Consider using Azure custom roles for the following key roles: Azure platform owner, network management, security operations, subscription owner, application owner", - "waf": "Security", - "guid": "f5664b5e-984a-4859-a773-e7d261623a76", - "id": "C03.10", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "If any data sovereignty requirements exist, Azure Policies can be deployed to enforce them", - "waf": "Security", - "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", - "id": "C03.11", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", - "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/" - }, - { - "category": "Identity and Access Management", - "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", - "waf": "Security", - "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", - "id": "C03.12", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "If AADDS in use, evaluate the compatibility of all workloads", - "waf": "Security", - "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", - "id": "C03.13", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", - "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "If AD on Windows server in use, can all required resources access correct domain controller?", - "waf": "Security", - "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", - "id": "C03.14", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain" - }, - { - "category": "Identity and Access Management", - "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).", - "waf": "Security", - "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", - "id": "C03.15", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy" - }, - { - "category": "Identity and Access Management", - "subcategory": "Identity", - "text": "Avoid using on-premises synced accounts for Azure AD role assignments.", - "waf": "Security", - "guid": "35037e68-9349-4c15-b371-228514f4cdff", - "id": "C03.16", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", - "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices" - }, - { - "category": "Identity and Access Management", - "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).", - "waf": "Security", - "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", - "id": "C04.01", - "severity": "Low", - "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities" - }, - { - "category": "Identity and Access Management", - "subcategory": "Landing zones", - "text": "Use Azure RBAC to manage data plane access to resources, if possible. E.G - Data Operations across Keyvault, Storage Account and Database Services. ", - "waf": "Security", - "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", - "id": "C04.02", - "severity": "Medium", - "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations" - }, - { - "category": "Identity and Access Management", - "subcategory": "Landing zones", - "text": "Use Azure AD PIM access reviews to periodically validate resource entitlements.", - "waf": "Security", - "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", - "id": "C04.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review" - }, - { - "category": "Management", - "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", - "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", - "id": "D01.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs" - }, - { - "category": "Management", - "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", - "guid": "7f408960-c626-44cb-a018-347c8d790cdf", - "id": "D01.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel" - }, - { - "category": "Management", - "subcategory": "Data Protection", - "text": "Consider cross-region replication in Azure for BCDR with paired regions", - "waf": "Reliability", - "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", - "id": "D02.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure" - }, - { - "category": "Management", - "subcategory": "Data Protection", - "text": "When using Azure Backup, consider the different backup types (GRS, ZRS & LRS) as the default setting is GRS", - "waf": "Reliability", - "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", - "id": "D02.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy" - }, - { - "category": "Management", - "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.", - "waf": "Operations", - "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", - "id": "D03.01", - "severity": "Medium", - "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Is the landing zone documented?", - "waf": "Operations", - "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", - "id": "D03.02", - "severity": "Medium" - }, - { - "category": "Management", - "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.", - "waf": "Operations", - "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", - "id": "D03.03", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work" - }, - { - "category": "Management", - "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. ", - "waf": "Operations", - "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", - "id": "D03.04", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Monitor in-guest virtual machine (VM) configuration drift using Azure Policy. Enabling guest configuration audit capabilities through policy helps application team workloads to immediately consume feature capabilities with little effort.", - "waf": "Operations", - "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", - "id": "D03.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Use Update Management in Azure Automation as a long-term patching mechanism for both Windows and Linux VMs. ", - "waf": "Operations", - "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", - "id": "D03.06", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", - "link": "https://learn.microsoft.com/azure/automation/update-management/overview" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Use Network Watcher to proactively monitor traffic flows", - "waf": "Operations", - "guid": "90483845-c986-4cb2-a131-56a12476e49f", - "id": "D03.07", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", - "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Use resource locks to prevent accidental deletion of critical shared services.", - "waf": "Operations", - "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", - "id": "D03.08", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json" - }, - { - "category": "Management", - "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", - "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", - "id": "D03.09", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/governance/policy/overview" - }, - { - "category": "Management", - "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", - "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", - "id": "D03.10", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal" - }, - { - "category": "Management", - "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", - "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", - "id": "D03.11", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups" - }, - { - "category": "Management", - "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", - "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", - "id": "D03.12", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard" - }, - { - "category": "Management", - "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", - "guid": "9945bda4-3334-4f24-a116-34182ba52752", - "id": "D03.13", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Use Azure Monitor Logs for insights and reporting.", - "waf": "Operations", - "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", - "id": "D03.14", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage.", - "waf": "Operations", - "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", - "id": "D03.15", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Use Azure Monitor alerts for the generation of operational alerts.", - "waf": "Operations", - "guid": "97be9951-9048-4384-9c98-6cb2913156a1", - "id": "D03.16", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied", - "waf": "Operations", - "guid": "859c3900-4514-41eb-b010-475d695abd74", - "id": "D03.17", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring" - }, - { - "category": "Management", - "subcategory": "Monitoring", - "text": "Consider supported regions for linked Log Analytics workspace and automation accounts", - "waf": "Operations", - "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", - "id": "D03.18", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings" - }, - { - "category": "Management", - "subcategory": "Operational complliance", - "text": "Use Azure policies to automatically deploy software configurations through VM extensions and enforce a compliant baseline VM configuration.", - "waf": "Security", - "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", - "id": "D04.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration" - }, - { - "category": "Management", - "subcategory": "Operational complliance", - "text": "Monitor VM security configuration drift via Azure Policy.", - "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.", - "waf": "Security", - "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", - "id": "D04.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift" - }, - { - "category": "Management", - "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", - "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", - "id": "D05.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview" - }, - { - "category": "Management", - "subcategory": "Protect and Recover", - "text": "Ensure to use and test native PaaS service disaster recovery capabilities.", - "waf": "Operations", - "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", - "id": "D05.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery" - }, - { - "category": "Management", - "subcategory": "Protect and Recover", - "text": "Use Azure-native backup capabilities, or an Azure-compatible, 3rd-party backup solution.", - "waf": "Operations", - "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", - "id": "D05.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/backup/backup-center-overview" - }, - { - "category": "Management ", - "subcategory": "Fault Tolerance", - "text": "Leverage Availability Zones for your VMs in regions where they are supported.", - "waf": "Reliability", - "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", - "id": "E01.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview" - }, - { - "category": "Management ", - "subcategory": "Fault Tolerance", - "text": "Avoid running a production workload on a single VM.", - "waf": "Reliability", - "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", - "id": "E01.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/virtual-machines/availability" - }, - { - "category": "Management ", - "subcategory": "Fault Tolerance", - "text": "Azure Load Balancer and Application Gateway distribute incoming network traffic across multiple resources.", - "waf": "Reliability", - "guid": "84101f59-1941-4195-a270-e28034290e3a", - "id": "E01.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview" - }, - { - "category": "Management ", - "subcategory": "Scalability", - "text": "Leverage Azure Virtual Machine Scale sets to scale up and down based on the load.", - "waf": "Reliability", - "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", - "id": "E02.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "id": "F01.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Perform app delivery within landing zones for both internal-facing (corp) and external-facing apps (online).", - "waf": "Security", - "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", - "id": "F01.02", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Ensure you are using Application Gateway v2 SKU", - "waf": "Security", - "guid": "553585a6-abe0-11ed-afa1-0242ac120002", - "id": "F01.03", - "severity": "Medium", - "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", - "waf": "Security", - "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", - "id": "F01.04", - "severity": "Medium", - "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", - "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26", - "waf": "Security", - "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", - "id": "F01.05", - "severity": "Medium", - "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", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "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.", - "waf": "Security", - "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", - "id": "F01.06", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", - "waf": "Security", - "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", - "id": "F01.07", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", - "id": "F01.08", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "3f29812b-2363-4cef-b179-b599de0d5973", - "id": "F01.09", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Use Traffic Manager to deliver global apps that span protocols other than HTTP/S.", - "waf": "Reliability", - "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", - "id": "F01.10", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "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)?", - "waf": "Security", - "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", - "id": "F01.11", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", - "id": "F01.12", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", - "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", - "waf": "Security", - "guid": "ae248989-b306-4591-9186-de482e3f0f0e", - "id": "F01.13", - "severity": "High", - "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", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", - "waf": "Security", - "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", - "id": "F01.14", - "severity": "High", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", - "id": "F01.15", - "severity": "High", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", - "waf": "Performance", - "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", - "id": "F01.16", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", - "id": "F01.17", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", - "id": "F01.18", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", - "waf": "Reliability", - "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", - "id": "F01.19", - "severity": "High", - "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", - "id": "F01.20", - "severity": "High", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", - "id": "F01.21", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", - "id": "F02.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works" - }, - { - "category": "Network Topology and Connectivity", - "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. ", - "waf": "Security", - "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", - "id": "F02.02", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", - "id": "F03.01", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity" - }, - { - "category": "Network Topology and Connectivity", - "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 Active Directory domain controllers and DNS servers.", - "waf": "Cost", - "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", - "id": "F03.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hub and spoke", - "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance", - "waf": "Reliability", - "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", - "id": "F03.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", - "id": "F03.04", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hub and spoke", - "text": "If using Route Server, use a /27 prefix for the Route Server subnet.", - "waf": "Security", - "guid": "91b9d7d5-91e1-4dcb-8f1f-fa7e465646cc", - "id": "F03.05", - "severity": "Low", - "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", - "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1" - }, - { - "category": "Network Topology and Connectivity", - "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. ", - "waf": "Performance", - "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", - "id": "F03.06", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-virtual-networks/", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-faq#can-i-create-a-peering-connection-to-a-vnet-in-a-different-region" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hub and spoke", - "text": "Use Azure Monitor for Networks to monitor the end-to-end state of the networks on Azure.", - "waf": "Operations", - "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", - "id": "F03.07", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", - "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "0e7c28ec-9366-4572-83b0-f4664b1d944a", - "id": "F03.08", - "severity": "Medium", - "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hub and spoke", - "text": "Consider the limit of routes per route table (400).", - "waf": "Reliability", - "guid": "3d457936-e9b7-41eb-bdff-314b26450b12", - "id": "F03.09", - "severity": "Medium", - "graph": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hub and spoke", - "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings", - "waf": "Reliability", - "guid": "c76cb5a2-abe2-11ed-afa1-0242ac120002", - "id": "F03.10", - "severity": "High", - "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Ensure that you have investigated the possibility to use ExpressRoute as primary connection to Azure.", - "waf": "Performance", - "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", - "id": "F04.01", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "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.", - "waf": "Reliability", - "guid": "f29812b2-363c-4efe-879b-599de0d5973c", - "id": "F04.02", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements.", - "waf": "Performance", - "guid": "d4cd21b0-8813-47f5-b6c4-cfd3e504547c", - "id": "F04.03", - "severity": "Medium", - "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", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost.", - "waf": "Cost", - "guid": "7025b442-f6e9-4af6-b11f-c9574916016f", - "id": "F04.04", - "severity": "High", - "graph": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "f4e7926a-ec35-476e-a412-5dd17136bd62", - "id": "F04.05", - "severity": "High", - "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", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions.", - "waf": "Reliability", - "guid": "2447ec66-138a-4720-8f1c-e16ed301d6e8", - "id": "F04.06", - "severity": "Medium", - "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", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "For scenarios that require bandwidth higher than 10 Gbps or dedicated 10/100-Gbps ports, use ExpressRoute Direct.", - "waf": "Performance", - "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", - "id": "F04.07", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/networking/" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Performance", - "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", - "id": "F04.08", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available).", - "waf": "Reliability", - "guid": "4d873974-8b66-42d6-b15f-512a65498f6d", - "id": "F04.09", - "severity": "Medium", - "graph": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant", - "training": "https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/", - "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "If using ExpressRoute Direct, consider using ExpressRoute Local circuits to the local Azure regions to save costs", - "waf": "Cost", - "guid": "718cb437-b060-2589-8856-2e93a5c6633b", - "id": "F04.10", - "severity": "High", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", - "id": "F04.11", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Monitor ExpressRoute availability and utilization using built-in Express Route Insights.", - "waf": "Operations", - "guid": "b30e38c3-f298-412b-8363-cefe179b599d", - "id": "F04.12", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Use Connection Monitor for connectivity monitoring across the environment.", - "waf": "Operations", - "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", - "id": "F04.13", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Hybrid", - "text": "Use ExpressRoute circuits from different peering locations for redundancy.", - "waf": "Reliability", - "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", - "id": "F04.14", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", - "id": "F04.15", - "severity": "High", - "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "IP plan", - "text": "Ensure no overlapping IP address spaces across Azure regions and on-premises locations are used", - "waf": "Security", - "guid": "558fd772-49b8-4211-82df-27ee412e7f98", - "id": "F05.01", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "IP plan", - "text": "Use IP addresses from the address allocation ranges for private internets (RFC 1918).", - "waf": "Security", - "guid": "3f630472-2dd6-49c5-a5c2-622f54b69bad", - "id": "F05.02", - "severity": "Low", - "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", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "IP plan", - "text": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16) ", - "waf": "Performance", - "guid": "33aad5e8-c68e-41d7-9667-313b4f5664b5", - "id": "F05.03", - "severity": "High", - "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", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "IP plan", - "text": "Avoid using overlapping IP address ranges for production and DR sites.", - "waf": "Reliability", - "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", - "id": "F05.04", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", - "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses" - }, - { - "category": "Network Topology and Connectivity", - "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').", - "waf": "Operations", - "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", - "id": "F05.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "IP plan", - "text": "For environments where name resolution across Azure and on-premises is required, consider using Azure DNS Private Resolver.", - "waf": "Security", - "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", - "id": "F05.06", - "severity": "Medium", - "training": "https://learn.microsoft.com/training/modules/intro-to-azure-dns-private-resolver/", - "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", - "id": "F05.07", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Operations", - "guid": "614658d3-558f-4d77-849b-821112df27ee", - "id": "F05.08", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", - "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Internet", - "text": "Consider using Azure Bastion to securely connect to your network.", - "waf": "Security", - "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", - "id": "F06.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/bastion/bastion-overview" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Internet", - "text": "Use Azure Bastion in a subnet /26 or larger.", - "waf": "Security", - "guid": "6eab9eb6-762b-485e-8ea8-15aa5dba0bd0", - "id": "F06.02", - "severity": "Medium", - "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", - "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet" - }, - { - "category": "Network Topology and Connectivity", - "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)", - "waf": "Security", - "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", - "id": "F06.03", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/app-service/networking-features" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", - "id": "F06.04", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/firewall/" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", - "id": "F06.05", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/firewall/" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", - "id": "F06.06", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", - "id": "F06.07", - "severity": "Low", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", - "id": "F06.08", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Internet", - "text": "Use Azure DDoS Network or IP Protection plans to help protect Public IP Addresses endpoints within the virtual networks.", - "waf": "Security", - "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", - "id": "F06.09", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", - "id": "F06.10", - "severity": "High", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Internet", - "text": "Use Azure Firewall Premium for additional security and protection.", - "waf": "Security", - "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", - "id": "F06.11", - "severity": "High", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/firewall/premium-features" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Internet", - "text": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection.", - "waf": "Security", - "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", - "id": "F06.12", - "severity": "High", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", - "link": "https://learn.microsoft.com/azure/firewall/premium-features" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Internet", - "text": "Configure Azure Firewall IDPS mode to Deny for additional protection.", - "waf": "Security", - "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", - "id": "F06.13", - "severity": "High", - "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", - "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "a3784907-9836-4271-aafc-93535f8ec08b", - "id": "F06.14", - "severity": "High", - "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", - "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", - "id": "F07.01", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", - "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "PaaS", - "text": "Use Private Link, where available, for shared Azure PaaS services.", - "waf": "Security", - "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", - "id": "F07.02", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", - "link": "https://learn.microsoft.com/azure/app-service/networking-features" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", - "id": "F07.03", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", - "link": "https://learn.microsoft.com/azure/app-service/networking-features" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "PaaS", - "text": "Don't enable virtual network service endpoints by default on all subnets.", - "waf": "Security", - "guid": "4704489a-8042-4d88-b79d-17b73b22a5a6", - "id": "F07.04", - "severity": "Medium", - "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", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", - "link": "https://learn.microsoft.com/azure/app-service/networking-features" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "PaaS", - "text": "If using virtual network service endpoints, filter egress FQDNs on an NVA to prevent data exfiltration.", - "waf": "Security", - "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", - "id": "F07.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", - "link": "https://learn.microsoft.com/azure/app-service/networking-features" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Segmentation", - "text": "Use a /26 prefix for your Azure Firewall subnets.", - "waf": "Security", - "guid": "22d6419e-b627-4d95-9e7d-019fa759387f", - "id": "F08.01", - "severity": "High", - "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", - "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Segmentation", - "text": "Use at least a /27 prefix for your Gateway subnets", - "waf": "Security", - "guid": "f2aad7e3-bb03-4adc-8606-4123d342a917", - "id": "F08.02", - "severity": "High", - "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", - "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Segmentation", - "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity.", - "waf": "Security", - "guid": "11deb39d-8299-4e47-bbe0-0fb5a36318a8", - "id": "F08.03", - "severity": "Medium", - "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)", - "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Segmentation", - "text": "Delegate subnet creation to the landing zone owner. ", - "waf": "Security", - "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", - "id": "F08.04", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Segmentation", - "text": "Use NSGs to help protect traffic across subnets, as well as east/west traffic across the platform (traffic between landing zones).", - "waf": "Security", - "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", - "id": "F08.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "9c2299c4-d7b5-47d0-a655-562f2b3e4563", - "id": "F08.06", - "severity": "Medium", - "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)", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/" - }, - { - "category": "Network Topology and Connectivity", - "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.", - "waf": "Security", - "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", - "id": "F08.07", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Segmentation", - "text": "Enable NSG flow logs and feed them into Traffic Analytics to gain insights into internal and external traffic flows.", - "waf": "Security", - "guid": "dfe237de-143b-416c-91d7-aa9b64704489", - "id": "F08.08", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", - "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works" - }, - { - "category": "Network Topology and Connectivity", - "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", - "waf": "Operations", - "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", - "id": "F09.01", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/introduction-azure-virtual-wan/", - "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", - "id": "F09.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", - "id": "F09.03", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Virtual WAN", - "text": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs", - "waf": "Security", - "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", - "id": "F09.04", - "severity": "Medium", - "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", - "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Virtual WAN", - "text": "Ensure that the network architecture is within the Azure Virtual WAN limits.", - "waf": "Reliability", - "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", - "id": "F09.05", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", - "id": "F09.06", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", - "id": "F09.07", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Virtual WAN", - "text": "Use AS-Path as hub routing preference, since it is more flexible than ExpressRoute or VPN.", - "waf": "Reliability", - "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", - "id": "F09.08", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference" - }, - { - "category": "Network Topology and Connectivity", - "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", - "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", - "id": "F09.09", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels" - }, - { - "category": "Network Topology and Connectivity", - "subcategory": "Virtual WAN", - "text": "Assign enough IP space to virtual hubs, ideally a /23 prefix.", - "waf": "Reliability", - "guid": "9c75dfef-573c-461c-a698-68598595581a", - "id": "F09.10", - "severity": "High", - "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", - "id": "G01.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", - "id": "G01.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection" - }, - { - "category": "Network topology and connectivity", - "subcategory": "App delivery", - "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", - "waf": "Security", - "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", - "id": "G01.03", - "severity": "High", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf" - }, - { - "category": "Network topology and connectivity", - "subcategory": "App delivery", - "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", - "waf": "Security", - "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", - "id": "G01.04", - "severity": "High", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf" - }, - { - "category": "Network topology and connectivity", - "subcategory": "App delivery", - "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", - "waf": "Security", - "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", - "id": "G01.05", - "severity": "High", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode" - }, - { - "category": "Network topology and connectivity", - "subcategory": "App delivery", - "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", - "waf": "Security", - "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", - "id": "G01.06", - "severity": "High", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets" - }, - { - "category": "Network topology and connectivity", - "subcategory": "App delivery", - "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", - "waf": "Security", - "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", - "id": "G01.07", - "severity": "High", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", - "id": "G01.08", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "b9620385-1cde-418f-914b-a84a06982ffc", - "id": "G01.09", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", - "id": "G01.10", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", - "id": "G01.11", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic" - }, - { - "category": "Network topology and connectivity", - "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", - "guid": "00acd8a9-6975-414f-8491-2be6309893b8", - "id": "G01.12", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", - "id": "H01.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops" - }, - { - "category": "Platform Automation and DevOps", - "subcategory": "DevOps Team Topologies", - "text": "Aim to define functions for Azure Landing Zone Platform team.", - "waf": "Operations", - "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", - "id": "H01.02", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", - "id": "H01.03", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "165eb5e9-b434-448a-9e24-178632186212", - "id": "H01.04", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code" - }, - { - "category": "Platform Automation and DevOps", - "subcategory": "DevOps Team Topologies", - "text": "Include unit tests for IaC and application code as part of your build process.", - "waf": "Operations", - "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", - "id": "H01.05", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", - "id": "H01.06", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds" - }, - { - "category": "Platform Automation and DevOps", - "subcategory": "DevOps Team Topologies", - "text": "Implement automation for File > New > Landing Zone for applications and workloads.", - "waf": "Operations", - "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", - "id": "H01.07", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending" - }, - { - "category": "Platform Automation and DevOps", - "subcategory": "Development Lifecycle", - "text": "Ensure a version control system is used for source code of applications and IaC developed. Microsoft recommends Git.", - "waf": "Operations", - "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", - "id": "H02.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", - "id": "H02.02", - "severity": "Low", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle" - }, - { - "category": "Platform Automation and DevOps", - "subcategory": "Development Lifecycle", - "text": "Adopt a pull request strategy to help keep control of code changes merged into branches.", - "waf": "Operations", - "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", - "id": "H02.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", - "id": "H03.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code" - }, - { - "category": "Platform Automation and DevOps", - "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", - "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", - "id": "H04.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure" - }, - { - "category": "Resource Organization", - "subcategory": "Naming and tagging", - "text": "It is recommended to follow Microsoft Best Practice Naming Standards", - "waf": "Security", - "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", - "id": "I01.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce reasonably flat management group hierarchy with no more than four levels.", - "waf": "Security", - "guid": "2df27ee4-12e7-4f98-9f63-04722dd69c5b", - "id": "I02.01", - "severity": "Medium", - "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)", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce or appended resource tags through Azure Policy", - "waf": "Security", - "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", - "id": "I02.02", - "severity": "Medium", - "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce a sandbox management group to allow users to immediately experiment with Azure", - "waf": "Security", - "guid": "667313b4-f566-44b5-b984-a859c773e7d2", - "id": "I02.03", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce a platform management group under the root management group to support common platform policy and Azure role assignment", - "waf": "Security", - "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", - "id": "I02.04", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations" - }, - { - "category": "Resource Organization", - "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.", - "waf": "Security", - "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", - "id": "I02.05", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce no subscriptions are placed under the root management group", - "waf": "Security", - "guid": "33b6b780-8b9f-4e5c-9104-9d403a923c34", - "id": "I02.06", - "severity": "Medium", - "graph": "resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1)", - "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group" - }, - { - "category": "Resource Organization", - "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", - "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", - "id": "I02.07", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization" - }, - { - "category": "Resource Organization", - "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", - "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", - "id": "I02.08", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview" - }, - { - "category": "Resource Organization", - "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", - "guid": "49b82111-2df2-47ee-912e-7f983f630472", - "id": "I02.09", - "severity": "High", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Ensure that all subscription owners and IT core team are aware of subscription resource limitations as part of workload design sessions.", - "waf": "Security", - "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", - "id": "I02.10", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" - }, - { - "category": "Resource Organization", - "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.", - "waf": "Security", - "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", - "id": "I02.11", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/improve-reliability-modern-operations/", - "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce a dashboard, workbook, or manual process to monitor used capacity levels", - "waf": "Security", - "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", - "id": "I02.12", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/monitor-usage-performance-availability-resources-azure-monitor/", - "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Ensure required services and features are available within the chosen deployment regions", - "waf": "Security", - "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", - "id": "I02.13", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", - "link": "https://azure.microsoft.com/global-infrastructure/services/" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Enforce a process for cost management", - "waf": "Security", - "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", - "id": "I02.14", - "severity": "High", - "training": "https://learn.microsoft.com/learn/paths/control-spending-manage-bills/", - "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview" - }, - { - "category": "Resource Organization", - "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", - "waf": "Security", - "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", - "id": "I02.15", - "severity": "Medium", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview" - }, - { - "category": "Resource Organization", - "subcategory": "Subscriptions", - "text": "Ensure tags are used for billing and cost management", - "waf": "Security", - "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", - "id": "I02.16", - "severity": "Medium", - "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs" - }, - { - "category": "Security", - "subcategory": "Access control", - "text": "Determine the incident response plan for Azure services before allowing it into production.", - "waf": "Security", - "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", - "id": "J01.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response" - }, - { - "category": "Security", - "subcategory": "Access control", - "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate.", - "waf": "Security", - "guid": "01365d38-e43f-49cc-ad86-8266abca264f", - "id": "J01.02", - "severity": "Medium", - "link": "https://www.microsoft.com/security/business/zero-trust" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "text": "Use Azure Key Vault to store your secrets and credentials", - "waf": "Security", - "guid": "5017f154-e3ab-4369-9829-e7e316183687", - "id": "J02.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview" - }, - { - "category": "Security", - "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", - "guid": "a0477a20-9945-4bda-9333-4f2491163418", - "id": "J02.02", - "severity": "Medium", - "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)", - "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling" - }, - { - "category": "Security", - "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", - "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", - "id": "J02.03", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "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", - "guid": "dc055bcf-619e-48a1-9f98-879525d62688", - "id": "J02.04", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "text": "Automate the certificate management and renewal process with public certificate authorities to ease administration.", - "waf": "Security", - "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", - "id": "J02.05", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "text": "Establish an automated process for key and certificate rotation.", - "waf": "Security", - "guid": "913156a1-2476-4e49-b541-acdce979377b", - "id": "J02.06", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "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", - "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", - "id": "J02.07", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "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", - "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", - "id": "J02.08", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "text": "Delegate Key Vault instantiation and privileged access and use Azure Policy to enforce a consistent compliant configuration.", - "waf": "Security", - "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", - "id": "J02.09", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required.", - "waf": "Security", - "guid": "16183687-a047-47a2-8994-5bda43334f24", - "id": "J02.10", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest" - }, - { - "category": "Security", - "subcategory": "Encryption and keys", - "text": "Use an Azure Key Vault per application per environment per region.", - "waf": "Security", - "guid": "91163418-2ba5-4275-8694-4008be7d7e48", - "id": "J02.11", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "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", - "guid": "25d62688-6d70-4ba6-a97b-e99519048384", - "id": "J02.12", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Use Azure AD reporting capabilities to generate access control audit reports.", - "waf": "Security", - "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", - "id": "J03.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports" - }, - { - "category": "Security", - "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", - "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", - "id": "J03.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Enable Defender Cloud Security Posture Management for all subscriptions.", - "waf": "Security", - "guid": "09945bda-4333-44f2-9911-634182ba5275", - "id": "J03.03", - "severity": "High", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Enable a Defender Cloud Workload Protection Plan for Servers on all subscriptions.", - "waf": "Security", - "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", - "id": "J03.04", - "severity": "High", - "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Enable Defender Cloud Workload Protection Plans for Azure Resources on all subscriptions.", - "waf": "Security", - "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", - "id": "J03.05", - "severity": "High", - "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Enable Endpoint Protection on IaaS Servers.", - "waf": "Security", - "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", - "id": "J03.06", - "severity": "High", - "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud.", - "waf": "Security", - "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", - "id": "J03.07", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/security-center/" - }, - { - "category": "Security", - "subcategory": "Operations", - "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace.", - "waf": "Security", - "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", - "id": "J03.08", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" - }, - { - "category": "Security", - "subcategory": "Overview", - "text": "Secure transfer to storage accounts should be enabled", - "waf": "Security", - "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", - "id": "J04.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer" - }, - { - "category": "Security", - "subcategory": "Overview", - "text": "Enable container soft delete for the storage account to recover a deleted container and its contents.", - "waf": "Security", - "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", - "id": "J04.02", - "severity": "High", - "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection" - }, - { - "category": "Security", - "subcategory": "Secure privileged access", - "text": "Separate privledged admin accounts for Azure administrative tasks.", - "waf": "Security", - "guid": "6f704104-85c1-441f-96d3-c9819911645e", - "id": "J05.01", - "severity": "High", - "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning" - }, - { - "category": "Security", - "subcategory": "Service enablement framework", - "text": "Plan how new azure services will be implemented", - "waf": "Security", - "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", - "id": "J06.01", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework" - }, - { - "category": "Security", - "subcategory": "Service enablement framework", - "text": "Plan how service request will be fulfilled for Azure services", - "waf": "Security", - "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", - "id": "J06.02", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework" + "items": [ + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Azure AD 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", + "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", + "id": "A01.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Azure AD Tenants", + "text": "Ensure you have a Multi-Tenant Automation approach to managing your Azure AD Tenants", + "waf": "Operations", + "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", + "id": "A01.02", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Azure AD Tenants", + "text": "Leverage Azure Lighthouse for Multi-Tenant Management", + "waf": "Operations", + "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", + "id": "A01.03", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Cloud Solution Provider", + "text": "Ensure that Azure Lighthouse is used for administering the tenant by partner", + "waf": "Cost", + "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", + "id": "A02.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Cloud Solution Provider", + "text": "Discuss support request and escalation process with CSP partner", + "waf": "Cost", + "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", + "id": "A02.02", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Cloud Solution Provider", + "text": "Setup Cost Reporting and Views with Azure Cost Management", + "waf": "Cost", + "guid": "32952499-58c8-4e6f-ada5-972e67893d55", + "id": "A02.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Enterprise Agreement", + "text": "Configure Notification Contacts to a group mailbox", + "waf": "Cost", + "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", + "id": "A03.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Enterprise Agreement", + "text": "Use departments and accounts to map your organization's structure to your enrollment hierarchy can help with separating billing.", + "waf": "Cost", + "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", + "id": "A03.02", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Enterprise Agreement", + "text": "Ensure that Accounts are configured to be of the type 'Work and School Account'", + "waf": "Security", + "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", + "id": "A03.03", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Enterprise Agreement", + "text": "Enable both DA View Charges and AO View Charges on your EA Enrollments to allowers users with the correct perms review Cost and Billing Data.", + "waf": "Security", + "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", + "id": "A03.04", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Enterprise Agreement", + "text": "Make use of Enterprise Dev/Test Subscriptions to reduce costs for non-production workloads", + "waf": "Cost", + "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", + "id": "A03.05", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Enterprise Agreement", + "text": "Periodically audit the role assignments to review who has access to your Enterprise Agreement Enrollment", + "waf": "Cost", + "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", + "id": "A03.06", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Microsoft Cloud Agreement", + "text": "Configure Agreement billing account notification contact email", + "waf": "Cost", + "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", + "id": "A04.01", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Microsoft Cloud Agreement", + "text": "Use Billing Profiles and Invoice sections to structure your agreements billing for effective cost management", + "waf": "Cost", + "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", + "id": "A04.02", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Microsoft Cloud Agreement", + "text": "Make use of Azure Plan to reduce costs for non-production workloads", + "waf": "Cost", + "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", + "id": "A04.03", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" + }, + { + "category": "Azure Billing and Active Directory Tenant", + "subcategory": "Microsoft Cloud Agreement", + "text": "Periodically audit the agreement billing RBAC role assignments to review who has access to your MCA billing account", + "waf": "Cost", + "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", + "id": "A04.04", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Leverage Azure Policy strategically, define controls for your environment, using Policy Initiatives to group related policies.", + "waf": "Security", + "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", + "id": "B01.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Identify required Azure tags and use the 'append' policy mode to enforce usage.", + "waf": "Security", + "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", + "id": "B01.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Map regulatory and compliance requirements to Azure Policy definitions and Azure role assignments.", + "waf": "Security", + "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", + "id": "B01.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Establish Azure Policy definitions at the top-level root management group so that they can be assigned at inherited scopes", + "waf": "Security", + "guid": "223ace8c-b123-408c-a501-7f154e3ab369", + "id": "B01.04", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Manage policy assignments at the highest appropriate level with exclusions at bottom levels, if required.", + "waf": "Security", + "guid": "3829e7e3-1618-4368-9a04-77a209945bda", + "id": "B01.05", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Use Azure Policy to control which services users can provision at the subscription/management group level", + "waf": "Security", + "guid": "43334f24-9116-4341-a2ba-527526944008", + "id": "B01.06", + "severity": "Low", + "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Use built-in policies where possible to minimize operational overhead.", + "waf": "Security", + "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", + "id": "B01.07", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Governance", + "subcategory": "Governance", + "text": "Assign the built-in Resource Policy Contributor role at a particular scope to enable application-level governance.", + "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.", + "waf": "Security", + "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", + "id": "B01.08", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy" + }, + { + "category": "Governance", + "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", + "guid": "19048384-5c98-46cb-8913-156a12476e49", + "id": "B01.09", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Governance", + "subcategory": "Optimize your cloud investment", + "text": "Consider using automation tags to start/stop VM's in your environment to save on cost.", + "waf": "Security", + "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", + "id": "B02.01", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config" + }, + { + "category": "Governance", + "subcategory": "Optimize your cloud investment", + "text": "Configure 'Actual' and 'Forecasted' Budget Alerts.", + "waf": "Cost", + "guid": "29fd366b-a180-452b-9bd7-954b7700c667", + "id": "B02.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cost-management-billing/costs/tutorial-acm-create-budgets?bc=%2Fazure%2Fcloud-adoption-framework%2F_bread%2Ftoc.json&toc=%2Fazure%2Fcloud-adoption-framework%2Ftoc.json" + }, + { + "category": "Identity and Access Management", + "subcategory": "Active Directory and Hybrid Identity", + "text": "Use managed identities instead of service principals for authentication to Azure services", + "waf": "Security", + "guid": "4348bf81-7573-4512-8f46-9061cc198fea", + "id": "C01.01", + "severity": "High", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator" + }, + { + "category": "Identity and Access Management", + "subcategory": "Azure AD", + "text": "When deploying an AD Connect VM, consider having a staging sever for high availability / Disaster recovery", + "waf": "Reliability", + "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", + "id": "C02.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Implement an emergency access or break-glass accounts to prevent tenant-wide account lockout", + "waf": "Security", + "guid": "984a859c-773e-47d2-9162-3a765a917e1f", + "id": "C03.01", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Integrate Azure AD 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", + "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", + "id": "C03.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Enforce a RBAC model that aligns to your cloud operating model. Scope and Assign across Management Groups and Subscriptions.", + "waf": "Security", + "guid": "348ef254-c27d-442e-abba-c7571559ab91", + "id": "C03.03", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/role-based-access-control/overview" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Enforce Azure AD conditional-access policies for any user with rights to Azure environments", + "waf": "Security", + "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", + "id": "C03.04", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/modules/plan-implement-administer-conditional-access/", + "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Enforce multi-factor authentication for any user with rights to the Azure environments", + "waf": "Security", + "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", + "id": "C03.05", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/secure-aad-users-with-mfa/", + "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Enforce centralized and delegated responsibilities to manage resources deployed inside the landing zone, based on role and security requirements", + "waf": "Security", + "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", + "id": "C03.06", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-identities-governance/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Enforce Azure AD Privileged Identity Management (PIM) to establish zero standing access and least privilege", + "waf": "Security", + "guid": "14658d35-58fd-4772-99b8-21112df27ee4", + "id": "C03.07", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/azure-ad-privileged-identity-management/", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Only use the authentication type Work or school account for all account types. Avoid using the Microsoft account", + "waf": "Security", + "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", + "id": "C03.08", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/explore-basic-services-identity-types/", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning#identify-microsoft-accounts-in-administrative-roles-that-need-to-be-switched-to-work-or-school-accounts" + }, + { + "category": "Identity and Access Management", + "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.", + "waf": "Security", + "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", + "id": "C03.09", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/manage-identity-and-access/", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Consider using Azure custom roles for the following key roles: Azure platform owner, network management, security operations, subscription owner, application owner", + "waf": "Security", + "guid": "f5664b5e-984a-4859-a773-e7d261623a76", + "id": "C03.10", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/create-custom-azure-roles-with-rbac/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "If any data sovereignty requirements exist, Azure Policies can be deployed to enforce them", + "waf": "Security", + "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", + "id": "C03.11", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-your-cloud-data/", + "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/" + }, + { + "category": "Identity and Access Management", + "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", + "waf": "Security", + "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", + "id": "C03.12", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/azure-active-directory/", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "If AADDS in use, evaluate the compatibility of all workloads", + "waf": "Security", + "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", + "id": "C03.13", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/implement-hybrid-identity-windows-server/", + "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "If AD on Windows server in use, can all required resources access correct domain controller?", + "waf": "Security", + "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", + "id": "C03.14", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-windows-server-iaas-virtual-machine-identity/", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain" + }, + { + "category": "Identity and Access Management", + "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).", + "waf": "Security", + "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", + "id": "C03.15", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy" + }, + { + "category": "Identity and Access Management", + "subcategory": "Identity", + "text": "Avoid using on-premises synced accounts for Azure AD role assignments.", + "waf": "Security", + "guid": "35037e68-9349-4c15-b371-228514f4cdff", + "id": "C03.16", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-identity-security-strategy/", + "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices" + }, + { + "category": "Identity and Access Management", + "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).", + "waf": "Security", + "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", + "id": "C04.01", + "severity": "Low", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities" + }, + { + "category": "Identity and Access Management", + "subcategory": "Landing zones", + "text": "Use Azure RBAC to manage data plane access to resources, if possible. E.G - Data Operations across Keyvault, Storage Account and Database Services. ", + "waf": "Security", + "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", + "id": "C04.02", + "severity": "Medium", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations" + }, + { + "category": "Identity and Access Management", + "subcategory": "Landing zones", + "text": "Use Azure AD PIM access reviews to periodically validate resource entitlements.", + "waf": "Security", + "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", + "id": "C04.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review" + }, + { + "category": "Management", + "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", + "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", + "id": "D01.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs" + }, + { + "category": "Management", + "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", + "guid": "7f408960-c626-44cb-a018-347c8d790cdf", + "id": "D01.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel" + }, + { + "category": "Management", + "subcategory": "Data Protection", + "text": "Consider cross-region replication in Azure for BCDR with paired regions", + "waf": "Reliability", + "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", + "id": "D02.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure" + }, + { + "category": "Management", + "subcategory": "Data Protection", + "text": "When using Azure Backup, consider the different backup types (GRS, ZRS & LRS) as the default setting is GRS", + "waf": "Reliability", + "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", + "id": "D02.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy" + }, + { + "category": "Management", + "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.", + "waf": "Operations", + "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", + "id": "D03.01", + "severity": "Medium", + "training": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Is the landing zone documented?", + "waf": "Operations", + "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "D03.02", + "severity": "Medium" + }, + { + "category": "Management", + "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.", + "waf": "Operations", + "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", + "id": "D03.03", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work" + }, + { + "category": "Management", + "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. ", + "waf": "Operations", + "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", + "id": "D03.04", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/architect-infrastructure-operations/", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Monitor in-guest virtual machine (VM) configuration drift using Azure Policy. Enabling guest configuration audit capabilities through policy helps application team workloads to immediately consume feature capabilities with little effort.", + "waf": "Operations", + "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", + "id": "D03.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Use Update Management in Azure Automation as a long-term patching mechanism for both Windows and Linux VMs. ", + "waf": "Operations", + "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", + "id": "D03.06", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-compute-resources/", + "link": "https://learn.microsoft.com/azure/automation/update-management/overview" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Use Network Watcher to proactively monitor traffic flows", + "waf": "Operations", + "guid": "90483845-c986-4cb2-a131-56a12476e49f", + "id": "D03.07", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/configure-network-watcher/", + "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Use resource locks to prevent accidental deletion of critical shared services.", + "waf": "Operations", + "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", + "id": "D03.08", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json" + }, + { + "category": "Management", + "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", + "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", + "id": "D03.09", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/governance/policy/overview" + }, + { + "category": "Management", + "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", + "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", + "id": "D03.10", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal" + }, + { + "category": "Management", + "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", + "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", + "id": "D03.11", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups" + }, + { + "category": "Management", + "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", + "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", + "id": "D03.12", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard" + }, + { + "category": "Management", + "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", + "guid": "9945bda4-3334-4f24-a116-34182ba52752", + "id": "D03.13", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Use Azure Monitor Logs for insights and reporting.", + "waf": "Operations", + "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", + "id": "D03.14", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "When necessary, use shared storage accounts within the landing zone for Azure diagnostic extension log storage.", + "waf": "Operations", + "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", + "id": "D03.15", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Use Azure Monitor alerts for the generation of operational alerts.", + "waf": "Operations", + "guid": "97be9951-9048-4384-9c98-6cb2913156a1", + "id": "D03.16", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Ensure that monitoring requirements have been assessed and that appropriate data collection and alerting configurations are applied", + "waf": "Operations", + "guid": "859c3900-4514-41eb-b010-475d695abd74", + "id": "D03.17", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring" + }, + { + "category": "Management", + "subcategory": "Monitoring", + "text": "Consider supported regions for linked Log Analytics workspace and automation accounts", + "waf": "Operations", + "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", + "id": "D03.18", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings" + }, + { + "category": "Management", + "subcategory": "Operational complliance", + "text": "Use Azure policies to automatically deploy software configurations through VM extensions and enforce a compliant baseline VM configuration.", + "waf": "Security", + "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", + "id": "D04.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration" + }, + { + "category": "Management", + "subcategory": "Operational complliance", + "text": "Monitor VM security configuration drift via Azure Policy.", + "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.", + "waf": "Security", + "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", + "id": "D04.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift" + }, + { + "category": "Management", + "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", + "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", + "id": "D05.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview" + }, + { + "category": "Management", + "subcategory": "Protect and Recover", + "text": "Ensure to use and test native PaaS service disaster recovery capabilities.", + "waf": "Operations", + "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", + "id": "D05.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery" + }, + { + "category": "Management", + "subcategory": "Protect and Recover", + "text": "Use Azure-native backup capabilities, or an Azure-compatible, 3rd-party backup solution.", + "waf": "Operations", + "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", + "id": "D05.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/backup/backup-center-overview" + }, + { + "category": "Management ", + "subcategory": "Fault Tolerance", + "text": "Leverage Availability Zones for your VMs in regions where they are supported.", + "waf": "Reliability", + "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", + "id": "E01.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview" + }, + { + "category": "Management ", + "subcategory": "Fault Tolerance", + "text": "Avoid running a production workload on a single VM.", + "waf": "Reliability", + "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", + "id": "E01.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/virtual-machines/availability" + }, + { + "category": "Management ", + "subcategory": "Fault Tolerance", + "text": "Azure Load Balancer and Application Gateway distribute incoming network traffic across multiple resources.", + "waf": "Reliability", + "guid": "84101f59-1941-4195-a270-e28034290e3a", + "id": "E01.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview" + }, + { + "category": "Management ", + "subcategory": "Scalability", + "text": "Leverage Azure Virtual Machine Scale sets to scale up and down based on the load.", + "waf": "Reliability", + "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", + "id": "E02.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "F01.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Perform app delivery within landing zones for both internal-facing (corp) and external-facing apps (online).", + "waf": "Security", + "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "F01.02", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Ensure you are using Application Gateway v2 SKU", + "waf": "Security", + "guid": "553585a6-abe0-11ed-afa1-0242ac120002", + "id": "F01.03", + "severity": "Medium", + "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Ensure you are using the Standard SKU for your Azure Load Balancers", + "waf": "Security", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "F01.04", + "severity": "Medium", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26", + "waf": "Security", + "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "F01.05", + "severity": "Medium", + "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", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "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.", + "waf": "Security", + "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "F01.06", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Use a DDoS Network or IP protection plans for all Public IP addresses in application landing zones.", + "waf": "Security", + "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "F01.07", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "F01.08", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "F01.09", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Use Traffic Manager to deliver global apps that span protocols other than HTTP/S.", + "waf": "Reliability", + "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "F01.10", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "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)?", + "waf": "Security", + "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "F01.11", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/modules/configure-azure-ad-application-proxy/", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "F01.12", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-applications-external-access-azure-ad/", + "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Deploy your WAF profiles for Front Door in 'Prevention' mode.", + "waf": "Security", + "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "F01.13", + "severity": "High", + "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", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Avoid combining Azure Traffic Manager and Azure Front Door.", + "waf": "Security", + "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "F01.14", + "severity": "High", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "F01.15", + "severity": "High", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Disable health probes when there is only one origin in an Azure Front Door origin group.", + "waf": "Performance", + "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "F01.16", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "F01.17", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "F01.18", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability", + "waf": "Reliability", + "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "F01.19", + "severity": "High", + "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "F01.20", + "severity": "High", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "F01.21", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "id": "F02.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works" + }, + { + "category": "Network Topology and Connectivity", + "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. ", + "waf": "Security", + "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "id": "F02.02", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", + "id": "F03.01", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity" + }, + { + "category": "Network Topology and Connectivity", + "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 Active Directory domain controllers and DNS servers.", + "waf": "Cost", + "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", + "id": "F03.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hub and spoke", + "text": "When deploying partner networking technologies or NVAs, follow the partner vendor's guidance", + "waf": "Reliability", + "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", + "id": "F03.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", + "id": "F03.04", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hub and spoke", + "text": "If using Route Server, use a /27 prefix for the Route Server subnet.", + "waf": "Security", + "guid": "91b9d7d5-91e1-4dcb-8f1f-fa7e465646cc", + "id": "F03.05", + "severity": "Low", + "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", + "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1" + }, + { + "category": "Network Topology and Connectivity", + "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. ", + "waf": "Performance", + "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "id": "F03.06", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/azure-administrator-manage-virtual-networks/", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-faq#can-i-create-a-peering-connection-to-a-vnet-in-a-different-region" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hub and spoke", + "text": "Use Azure Monitor for Networks to monitor the end-to-end state of the networks on Azure.", + "waf": "Operations", + "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", + "id": "F03.07", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", + "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "0e7c28ec-9366-4572-83b0-f4664b1d944a", + "id": "F03.08", + "severity": "Medium", + "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hub and spoke", + "text": "Consider the limit of routes per route table (400).", + "waf": "Reliability", + "guid": "3d457936-e9b7-41eb-bdff-314b26450b12", + "id": "F03.09", + "severity": "Medium", + "graph": "resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hub and spoke", + "text": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings", + "waf": "Reliability", + "guid": "c76cb5a2-abe2-11ed-afa1-0242ac120002", + "id": "F03.10", + "severity": "High", + "graph": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Ensure that you have investigated the possibility to use ExpressRoute as primary connection to Azure.", + "waf": "Performance", + "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", + "id": "F04.01", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "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.", + "waf": "Reliability", + "guid": "f29812b2-363c-4efe-879b-599de0d5973c", + "id": "F04.02", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements.", + "waf": "Performance", + "guid": "d4cd21b0-8813-47f5-b6c4-cfd3e504547c", + "id": "F04.03", + "severity": "Medium", + "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", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost.", + "waf": "Cost", + "guid": "7025b442-f6e9-4af6-b11f-c9574916016f", + "id": "F04.04", + "severity": "High", + "graph": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "f4e7926a-ec35-476e-a412-5dd17136bd62", + "id": "F04.05", + "severity": "High", + "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", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions.", + "waf": "Reliability", + "guid": "2447ec66-138a-4720-8f1c-e16ed301d6e8", + "id": "F04.06", + "severity": "Medium", + "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", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "For scenarios that require bandwidth higher than 10 Gbps or dedicated 10/100-Gbps ports, use ExpressRoute Direct.", + "waf": "Performance", + "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", + "id": "F04.07", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/networking/" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Performance", + "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", + "id": "F04.08", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available).", + "waf": "Reliability", + "guid": "4d873974-8b66-42d6-b15f-512a65498f6d", + "id": "F04.09", + "severity": "Medium", + "graph": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant", + "training": "https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/", + "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "If using ExpressRoute Direct, consider using ExpressRoute Local circuits to the local Azure regions to save costs", + "waf": "Cost", + "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "id": "F04.10", + "severity": "High", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "id": "F04.11", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Monitor ExpressRoute availability and utilization using built-in Express Route Insights.", + "waf": "Operations", + "guid": "b30e38c3-f298-412b-8363-cefe179b599d", + "id": "F04.12", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Use Connection Monitor for connectivity monitoring across the environment.", + "waf": "Operations", + "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", + "id": "F04.13", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Hybrid", + "text": "Use ExpressRoute circuits from different peering locations for redundancy.", + "waf": "Reliability", + "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", + "id": "F04.14", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "id": "F04.15", + "severity": "High", + "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "IP plan", + "text": "Ensure no overlapping IP address spaces across Azure regions and on-premises locations are used", + "waf": "Security", + "guid": "558fd772-49b8-4211-82df-27ee412e7f98", + "id": "F05.01", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "IP plan", + "text": "Use IP addresses from the address allocation ranges for private internets (RFC 1918).", + "waf": "Security", + "guid": "3f630472-2dd6-49c5-a5c2-622f54b69bad", + "id": "F05.02", + "severity": "Low", + "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", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "IP plan", + "text": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16) ", + "waf": "Performance", + "guid": "33aad5e8-c68e-41d7-9667-313b4f5664b5", + "id": "F05.03", + "severity": "High", + "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", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "IP plan", + "text": "Avoid using overlapping IP address ranges for production and DR sites.", + "waf": "Reliability", + "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", + "id": "F05.04", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses" + }, + { + "category": "Network Topology and Connectivity", + "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').", + "waf": "Operations", + "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", + "id": "F05.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "IP plan", + "text": "For environments where name resolution across Azure and on-premises is required, consider using Azure DNS Private Resolver.", + "waf": "Security", + "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", + "id": "F05.06", + "severity": "Medium", + "training": "https://learn.microsoft.com/training/modules/intro-to-azure-dns-private-resolver/", + "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", + "id": "F05.07", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Operations", + "guid": "614658d3-558f-4d77-849b-821112df27ee", + "id": "F05.08", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/az-104-manage-virtual-networks/", + "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Internet", + "text": "Consider using Azure Bastion to securely connect to your network.", + "waf": "Security", + "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "id": "F06.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/bastion/bastion-overview" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Internet", + "text": "Use Azure Bastion in a subnet /26 or larger.", + "waf": "Security", + "guid": "6eab9eb6-762b-485e-8ea8-15aa5dba0bd0", + "id": "F06.02", + "severity": "Medium", + "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", + "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet" + }, + { + "category": "Network Topology and Connectivity", + "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)", + "waf": "Security", + "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", + "id": "F06.03", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/app-service/networking-features" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", + "id": "F06.04", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/firewall/" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", + "id": "F06.05", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/firewall/" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", + "id": "F06.06", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", + "id": "F06.07", + "severity": "Low", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", + "id": "F06.08", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/architect-network-infrastructure/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Internet", + "text": "Use Azure DDoS Network or IP Protection plans to help protect Public IP Addresses endpoints within the virtual networks.", + "waf": "Security", + "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", + "id": "F06.09", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "id": "F06.10", + "severity": "High", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Internet", + "text": "Use Azure Firewall Premium for additional security and protection.", + "waf": "Security", + "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "id": "F06.11", + "severity": "High", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/firewall/premium-features" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Internet", + "text": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection.", + "waf": "Security", + "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "id": "F06.12", + "severity": "High", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", + "link": "https://learn.microsoft.com/azure/firewall/premium-features" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Internet", + "text": "Configure Azure Firewall IDPS mode to Deny for additional protection.", + "waf": "Security", + "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "id": "F06.13", + "severity": "High", + "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", + "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "a3784907-9836-4271-aafc-93535f8ec08b", + "id": "F06.14", + "severity": "High", + "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", + "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "F07.01", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "PaaS", + "text": "Use Private Link, where available, for shared Azure PaaS services.", + "waf": "Security", + "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", + "id": "F07.02", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", + "link": "https://learn.microsoft.com/azure/app-service/networking-features" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", + "id": "F07.03", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/", + "link": "https://learn.microsoft.com/azure/app-service/networking-features" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "PaaS", + "text": "Don't enable virtual network service endpoints by default on all subnets.", + "waf": "Security", + "guid": "4704489a-8042-4d88-b79d-17b73b22a5a6", + "id": "F07.04", + "severity": "Medium", + "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", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "link": "https://learn.microsoft.com/azure/app-service/networking-features" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "PaaS", + "text": "If using virtual network service endpoints, filter egress FQDNs on an NVA to prevent data exfiltration.", + "waf": "Security", + "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", + "id": "F07.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn", + "link": "https://learn.microsoft.com/azure/app-service/networking-features" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Segmentation", + "text": "Use a /26 prefix for your Azure Firewall subnets.", + "waf": "Security", + "guid": "22d6419e-b627-4d95-9e7d-019fa759387f", + "id": "F08.01", + "severity": "High", + "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", + "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Segmentation", + "text": "Use at least a /27 prefix for your Gateway subnets", + "waf": "Security", + "guid": "f2aad7e3-bb03-4adc-8606-4123d342a917", + "id": "F08.02", + "severity": "High", + "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", + "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Segmentation", + "text": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity.", + "waf": "Security", + "guid": "11deb39d-8299-4e47-bbe0-0fb5a36318a8", + "id": "F08.03", + "severity": "Medium", + "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)", + "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Segmentation", + "text": "Delegate subnet creation to the landing zone owner. ", + "waf": "Security", + "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", + "id": "F08.04", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Segmentation", + "text": "Use NSGs to help protect traffic across subnets, as well as east/west traffic across the platform (traffic between landing zones).", + "waf": "Security", + "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", + "id": "F08.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "9c2299c4-d7b5-47d0-a655-562f2b3e4563", + "id": "F08.06", + "severity": "Medium", + "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)", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/" + }, + { + "category": "Network Topology and Connectivity", + "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.", + "waf": "Security", + "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", + "id": "F08.07", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/implement-network-security/", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Segmentation", + "text": "Enable NSG flow logs and feed them into Traffic Analytics to gain insights into internal and external traffic flows.", + "waf": "Security", + "guid": "dfe237de-143b-416c-91d7-aa9b64704489", + "id": "F08.08", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/design-implement-network-monitoring/", + "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works" + }, + { + "category": "Network Topology and Connectivity", + "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", + "waf": "Operations", + "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", + "id": "F09.01", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/introduction-azure-virtual-wan/", + "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", + "id": "F09.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", + "id": "F09.03", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Virtual WAN", + "text": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs", + "waf": "Security", + "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", + "id": "F09.04", + "severity": "Medium", + "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", + "training": "https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Virtual WAN", + "text": "Ensure that the network architecture is within the Azure Virtual WAN limits.", + "waf": "Reliability", + "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "id": "F09.05", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "id": "F09.06", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "id": "F09.07", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Virtual WAN", + "text": "Use AS-Path as hub routing preference, since it is more flexible than ExpressRoute or VPN.", + "waf": "Reliability", + "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "id": "F09.08", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference" + }, + { + "category": "Network Topology and Connectivity", + "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", + "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "id": "F09.09", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels" + }, + { + "category": "Network Topology and Connectivity", + "subcategory": "Virtual WAN", + "text": "Assign enough IP space to virtual hubs, ideally a /23 prefix.", + "waf": "Reliability", + "guid": "9c75dfef-573c-461c-a698-68598595581a", + "id": "F09.10", + "severity": "High", + "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "G01.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "G01.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection" + }, + { + "category": "Network topology and connectivity", + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF. Protect your application from a range of attacks.", + "waf": "Security", + "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "G01.03", + "severity": "High", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf" + }, + { + "category": "Network topology and connectivity", + "subcategory": "App delivery", + "text": "Tune the Azure Front Door WAF for your workload. Reduce false positive detections.", + "waf": "Security", + "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "G01.04", + "severity": "High", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf" + }, + { + "category": "Network topology and connectivity", + "subcategory": "App delivery", + "text": "Use prevention mode with the Azure Front Door WAF. Prevention mode ensures that the WAF blocks malicious requests.", + "waf": "Security", + "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "G01.05", + "severity": "High", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode" + }, + { + "category": "Network topology and connectivity", + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF default rule sets. The default rule sets detect and block common attacks.", + "waf": "Security", + "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "G01.06", + "severity": "High", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets" + }, + { + "category": "Network topology and connectivity", + "subcategory": "App delivery", + "text": "Enable the Azure Front Door WAF bot management rules. The bot rules detect good and bad bots.", + "waf": "Security", + "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "G01.07", + "severity": "High", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "G01.08", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "G01.09", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "G01.10", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "G01.11", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic" + }, + { + "category": "Network topology and connectivity", + "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", + "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "G01.12", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", + "id": "H01.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops" + }, + { + "category": "Platform Automation and DevOps", + "subcategory": "DevOps Team Topologies", + "text": "Aim to define functions for Azure Landing Zone Platform team.", + "waf": "Operations", + "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", + "id": "H01.02", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", + "id": "H01.03", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "165eb5e9-b434-448a-9e24-178632186212", + "id": "H01.04", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code" + }, + { + "category": "Platform Automation and DevOps", + "subcategory": "DevOps Team Topologies", + "text": "Include unit tests for IaC and application code as part of your build process.", + "waf": "Operations", + "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", + "id": "H01.05", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", + "id": "H01.06", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds" + }, + { + "category": "Platform Automation and DevOps", + "subcategory": "DevOps Team Topologies", + "text": "Implement automation for File > New > Landing Zone for applications and workloads.", + "waf": "Operations", + "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", + "id": "H01.07", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending" + }, + { + "category": "Platform Automation and DevOps", + "subcategory": "Development Lifecycle", + "text": "Ensure a version control system is used for source code of applications and IaC developed. Microsoft recommends Git.", + "waf": "Operations", + "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", + "id": "H02.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", + "id": "H02.02", + "severity": "Low", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle" + }, + { + "category": "Platform Automation and DevOps", + "subcategory": "Development Lifecycle", + "text": "Adopt a pull request strategy to help keep control of code changes merged into branches.", + "waf": "Operations", + "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", + "id": "H02.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", + "id": "H03.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code" + }, + { + "category": "Platform Automation and DevOps", + "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", + "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", + "id": "H04.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure" + }, + { + "category": "Resource Organization", + "subcategory": "Naming and tagging", + "text": "It is recommended to follow Microsoft Best Practice Naming Standards", + "waf": "Security", + "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", + "id": "I01.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce reasonably flat management group hierarchy with no more than four levels.", + "waf": "Security", + "guid": "2df27ee4-12e7-4f98-9f63-04722dd69c5b", + "id": "I02.01", + "severity": "Medium", + "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)", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce or appended resource tags through Azure Policy", + "waf": "Security", + "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", + "id": "I02.02", + "severity": "Medium", + "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce a sandbox management group to allow users to immediately experiment with Azure", + "waf": "Security", + "guid": "667313b4-f566-44b5-b984-a859c773e7d2", + "id": "I02.03", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce a platform management group under the root management group to support common platform policy and Azure role assignment", + "waf": "Security", + "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", + "id": "I02.04", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations" + }, + { + "category": "Resource Organization", + "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.", + "waf": "Security", + "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", + "id": "I02.05", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce no subscriptions are placed under the root management group", + "waf": "Security", + "guid": "33b6b780-8b9f-4e5c-9104-9d403a923c34", + "id": "I02.06", + "severity": "Medium", + "graph": "resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1)", + "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group" + }, + { + "category": "Resource Organization", + "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", + "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", + "id": "I02.07", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization" + }, + { + "category": "Resource Organization", + "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", + "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", + "id": "I02.08", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview" + }, + { + "category": "Resource Organization", + "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", + "guid": "49b82111-2df2-47ee-912e-7f983f630472", + "id": "I02.09", + "severity": "High", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Ensure that all subscription owners and IT core team are aware of subscription resource limitations as part of workload design sessions.", + "waf": "Security", + "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", + "id": "I02.10", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" + }, + { + "category": "Resource Organization", + "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.", + "waf": "Security", + "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", + "id": "I02.11", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/improve-reliability-modern-operations/", + "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce a dashboard, workbook, or manual process to monitor used capacity levels", + "waf": "Security", + "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", + "id": "I02.12", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/monitor-usage-performance-availability-resources-azure-monitor/", + "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Ensure required services and features are available within the chosen deployment regions", + "waf": "Security", + "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "I02.13", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/", + "link": "https://azure.microsoft.com/global-infrastructure/services/" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Enforce a process for cost management", + "waf": "Security", + "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "I02.14", + "severity": "High", + "training": "https://learn.microsoft.com/learn/paths/control-spending-manage-bills/", + "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview" + }, + { + "category": "Resource Organization", + "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", + "waf": "Security", + "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "I02.15", + "severity": "Medium", + "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/", + "link": "https://learn.microsoft.com/azure/governance/management-groups/overview" + }, + { + "category": "Resource Organization", + "subcategory": "Subscriptions", + "text": "Ensure tags are used for billing and cost management", + "waf": "Security", + "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", + "id": "I02.16", + "severity": "Medium", + "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", + "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs" + }, + { + "category": "Security", + "subcategory": "Access control", + "text": "Determine the incident response plan for Azure services before allowing it into production.", + "waf": "Security", + "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", + "id": "J01.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response" + }, + { + "category": "Security", + "subcategory": "Access control", + "text": "Implement a zero-trust approach for access to the Azure platform, where appropriate.", + "waf": "Security", + "guid": "01365d38-e43f-49cc-ad86-8266abca264f", + "id": "J01.02", + "severity": "Medium", + "link": "https://www.microsoft.com/security/business/zero-trust" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "text": "Use Azure Key Vault to store your secrets and credentials", + "waf": "Security", + "guid": "5017f154-e3ab-4369-9829-e7e316183687", + "id": "J02.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview" + }, + { + "category": "Security", + "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", + "guid": "a0477a20-9945-4bda-9333-4f2491163418", + "id": "J02.02", + "severity": "Medium", + "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)", + "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling" + }, + { + "category": "Security", + "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", + "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", + "id": "J02.03", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "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", + "guid": "dc055bcf-619e-48a1-9f98-879525d62688", + "id": "J02.04", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "text": "Automate the certificate management and renewal process with public certificate authorities to ease administration.", + "waf": "Security", + "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "J02.05", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "text": "Establish an automated process for key and certificate rotation.", + "waf": "Security", + "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "J02.06", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "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", + "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", + "id": "J02.07", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "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", + "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", + "id": "J02.08", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "text": "Delegate Key Vault instantiation and privileged access and use Azure Policy to enforce a consistent compliant configuration.", + "waf": "Security", + "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", + "id": "J02.09", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "text": "Default to Microsoft-managed keys for principal encryption functionality and use customer-managed keys when required.", + "waf": "Security", + "guid": "16183687-a047-47a2-8994-5bda43334f24", + "id": "J02.10", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest" + }, + { + "category": "Security", + "subcategory": "Encryption and keys", + "text": "Use an Azure Key Vault per application per environment per region.", + "waf": "Security", + "guid": "91163418-2ba5-4275-8694-4008be7d7e48", + "id": "J02.11", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "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", + "guid": "25d62688-6d70-4ba6-a97b-e99519048384", + "id": "J02.12", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Use Azure AD reporting capabilities to generate access control audit reports.", + "waf": "Security", + "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", + "id": "J03.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports" + }, + { + "category": "Security", + "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", + "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", + "id": "J03.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Enable Defender Cloud Security Posture Management for all subscriptions.", + "waf": "Security", + "guid": "09945bda-4333-44f2-9911-634182ba5275", + "id": "J03.03", + "severity": "High", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Enable a Defender Cloud Workload Protection Plan for Servers on all subscriptions.", + "waf": "Security", + "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", + "id": "J03.04", + "severity": "High", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Enable Defender Cloud Workload Protection Plans for Azure Resources on all subscriptions.", + "waf": "Security", + "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", + "id": "J03.05", + "severity": "High", + "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Enable Endpoint Protection on IaaS Servers.", + "waf": "Security", + "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", + "id": "J03.06", + "severity": "High", + "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Monitor base operating system patching drift via Azure Monitor Logs and Defender for Cloud.", + "waf": "Security", + "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "J03.07", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/security-center/" + }, + { + "category": "Security", + "subcategory": "Operations", + "text": "Connect default resource configurations to a centralized Azure Monitor Log Analytics workspace.", + "waf": "Security", + "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", + "id": "J03.08", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment" + }, + { + "category": "Security", + "subcategory": "Overview", + "text": "Secure transfer to storage accounts should be enabled", + "waf": "Security", + "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", + "id": "J04.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer" + }, + { + "category": "Security", + "subcategory": "Overview", + "text": "Enable container soft delete for the storage account to recover a deleted container and its contents.", + "waf": "Security", + "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", + "id": "J04.02", + "severity": "High", + "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection" + }, + { + "category": "Security", + "subcategory": "Secure privileged access", + "text": "Separate privledged admin accounts for Azure administrative tasks.", + "waf": "Security", + "guid": "6f704104-85c1-441f-96d3-c9819911645e", + "id": "J05.01", + "severity": "High", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning" + }, + { + "category": "Security", + "subcategory": "Service enablement framework", + "text": "Plan how new azure services will be implemented", + "waf": "Security", + "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", + "id": "J06.01", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework" + }, + { + "category": "Security", + "subcategory": "Service enablement framework", + "text": "Plan how service request will be fulfilled for Azure services", + "waf": "Security", + "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", + "id": "J06.02", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework" + } + ], + "categories": [ + { + "name": "Azure Billing and Active Directory Tenant" + }, + { + "name": "Identity and Access Management" + }, + { + "name": "Network Topology and Connectivity" + }, + { + "name": "Security" + }, + { + "name": "Management" + }, + { + "name": "Resource Organization" + }, + { + "name": "Platform Automation and DevOps" + }, + { + "name": "Governance" + } + ], + "waf": [ + { + "name": "Reliability" + }, + { + "name": "Security" + }, + { + "name": "Cost" + }, + { + "name": "Operations" + }, + { + "name": "Performance" + } + ], + "status": [ + { + "name": "Not verified", + "description": "This check has not been looked at yet" + }, + { + "name": "Open", + "description": "There is an action item associated to this check" + }, + { + "name": "Fulfilled", + "description": "This check has been verified, and there are no further action items associated to it" + }, + { + "name": "Not required", + "description": "Recommendation understood, but not needed by current requirements" + }, + { + "name": "N/A", + "description": "Not applicable for current design" + } + ], + "severities": [ + { + "name": "High" + }, + { + "name": "Medium" + }, + { + "name": "Low" + } + ], + "metadata": { + "name": "Azure Landing Zone Review", + "state": "GA", + "timestamp": "September 14, 2023" } - ], - "categories": [ - { - "name": "Azure Billing and Active Directory Tenant" - }, - { - "name": "Identity and Access Management" - }, - { - "name": "Network Topology and Connectivity" - }, - { - "name": "Security" - }, - { - "name": "Management" - }, - { - "name": "Resource Organization" - }, - { - "name": "Platform Automation and DevOps" - }, - { - "name": "Governance" - } - ], - "waf": [ - { - "name": "Reliability" - }, - { - "name": "Security" - }, - { - "name": "Cost" - }, - { - "name": "Operations" - }, - { - "name": "Performance" - } - ], - "status": [ - { - "name": "Not verified", - "description": "This check has not been looked at yet" - }, - { - "name": "Open", - "description": "There is an action item associated to this check" - }, - { - "name": "Fulfilled", - "description": "This check has been verified, and there are no further action items associated to it" - }, - { - "name": "Not required", - "description": "Recommendation understood, but not needed by current requirements" - }, - { - "name": "N/A", - "description": "Not applicable for current design" - } - ], - "severities": [ - { - "name": "High" - }, - { - "name": "Medium" - }, - { - "name": "Low" - } - ], - "metadata": { - "name": "Azure Landing Zone Review", - "state": "GA", - "timestamp": "09/14/2023 14:58:41" - } -} +} \ No newline at end of file diff --git a/checklists/alz_checklist.es.json b/checklists/alz_checklist.es.json index 0ebbfdb3c..eae6dac66 100644 --- a/checklists/alz_checklist.es.json +++ b/checklists/alz_checklist.es.json @@ -29,17 +29,19 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", - "link": "https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/considerations/tenancy-models", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations", "severity": "Medio", "subcategory": "Inquilinos de Azure AD", - "text": "¿Cuántos inquilinos de Azure AD administra?", + "text": "Use un inquilino de Entra para administrar los recursos de Azure, a menos que tenga un requisito normativo o empresarial claro para los multiinquilinos.", "waf": "Operaciones" }, { "category": "Inquilino de Azure Billing y Active Directory", "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", - "severity": "Medio", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", + "severity": "Bajo", "subcategory": "Inquilinos de Azure AD", "text": "Asegúrese de que tiene un enfoque de automatización multiinquilino para administrar sus inquilinos de Azure AD", "waf": "Operaciones" @@ -47,8 +49,9 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", - "severity": "Medio", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "severity": "Bajo", "subcategory": "Inquilinos de Azure AD", "text": "Aproveche Azure Lighthouse para la administración de varios inquilinos", "waf": "Operaciones" @@ -56,7 +59,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Medio", "subcategory": "Proveedor de soluciones en la nube", "text": "Asegúrese de que Azure Lighthouse se usa para administrar el inquilino por asociado", @@ -65,7 +69,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Bajo", "subcategory": "Proveedor de soluciones en la nube", "text": "Discutir la solicitud de soporte y el proceso de escalamiento con el socio de CSP", @@ -74,7 +79,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "32952499-58c8-4e6f-ada5-972e67893d55", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Medio", "subcategory": "Proveedor de soluciones en la nube", "text": "Configuración de informes de costos y vistas con Azure Cost Management", @@ -83,7 +89,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "severity": "Medio", "subcategory": "Contrato Enterprise", "text": "Configurar contactos de notificación en un buzón de grupo", @@ -92,7 +99,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Bajo", "subcategory": "Contrato Enterprise", "text": "Usar departamentos y cuentas para asignar la estructura de su organización a su jerarquía de inscripción puede ayudar a separar la facturación.", @@ -101,7 +109,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Alto", "subcategory": "Contrato Enterprise", "text": "Asegúrese de que las cuentas estén configuradas para ser del tipo \"Cuenta profesional y educativa\"", @@ -110,7 +119,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Medio", "subcategory": "Contrato Enterprise", "text": "Habilite los cargos de vista de DA y los cargos de vista de AO en sus inscripciones de EA para los usuarios permitidos con los datos de costo y facturación de revisión de permanentes correctos.", @@ -119,7 +129,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Bajo", "subcategory": "Contrato Enterprise", "text": "Utilice las suscripciones de desarrollo y pruebas empresariales para reducir los costos de las cargas de trabajo que no son de producción", @@ -128,7 +139,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Medio", "subcategory": "Contrato Enterprise", "text": "Audite periódicamente las asignaciones de roles para revisar quién tiene acceso a su inscripción en el Contrato Enterprise", @@ -137,7 +149,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Bajo", "subcategory": "Contrato de nube de Microsoft", "text": "Configurar el acuerdo de notificación de cuenta de facturación correo electrónico de contacto", @@ -146,7 +159,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/mca-section-invoice", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "severity": "Bajo", "subcategory": "Contrato de nube de Microsoft", "text": "Utilice las secciones Perfiles de facturación y Facturas para estructurar la facturación de sus acuerdos para una gestión eficaz de los costes", @@ -155,7 +169,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Bajo", "subcategory": "Contrato de nube de Microsoft", "text": "Uso de Azure Plan para reducir los costos de las cargas de trabajo que no son de producción", @@ -164,7 +179,8 @@ { "category": "Inquilino de Azure Billing y Active Directory", "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Medio", "subcategory": "Contrato de nube de Microsoft", "text": "Audite periódicamente las asignaciones de roles RBAC de facturación del acuerdo para revisar quién tiene acceso a su cuenta de facturación de MCA", @@ -173,6 +189,7 @@ { "category": "Gobernanza", "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", + "id": "B01.01", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Alto", "subcategory": "Gobernanza", @@ -182,6 +199,7 @@ { "category": "Gobernanza", "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", + "id": "B01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", "severity": "Medio", "subcategory": "Gobernanza", @@ -191,6 +209,7 @@ { "category": "Gobernanza", "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", + "id": "B01.03", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Medio", "subcategory": "Gobernanza", @@ -200,6 +219,7 @@ { "category": "Gobernanza", "guid": "223ace8c-b123-408c-a501-7f154e3ab369", + "id": "B01.04", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Medio", "subcategory": "Gobernanza", @@ -209,6 +229,7 @@ { "category": "Gobernanza", "guid": "3829e7e3-1618-4368-9a04-77a209945bda", + "id": "B01.05", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Medio", "subcategory": "Gobernanza", @@ -218,6 +239,7 @@ { "category": "Gobernanza", "guid": "43334f24-9116-4341-a2ba-527526944008", + "id": "B01.06", "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "severity": "Bajo", "subcategory": "Gobernanza", @@ -227,6 +249,7 @@ { "category": "Gobernanza", "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", + "id": "B01.07", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Medio", "subcategory": "Gobernanza", @@ -237,6 +260,7 @@ "category": "Gobernanza", "description": "La asignación del rol Colaborador de directivas de recursos a ámbitos específicos permite delegar la administración de directivas a los equipos pertinentes. Por ejemplo, un equipo central de TI puede supervisar las políticas de nivel de grupo de administración, mientras que los equipos de aplicaciones manejan las políticas para sus suscripciones, lo que permite un gobierno distribuido con el cumplimiento de los estándares de la organización.", "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", + "id": "B01.08", "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "severity": "Medio", "subcategory": "Gobernanza", @@ -246,6 +270,7 @@ { "category": "Gobernanza", "guid": "19048384-5c98-46cb-8913-156a12476e49", + "id": "B01.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Medio", "subcategory": "Gobernanza", @@ -255,7 +280,8 @@ { "category": "Gobernanza", "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", - "link": "https://learn.microsoft.com/en-us/azure/automation/automation-solution-vm-management-config", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "severity": "Bajo", "subcategory": "Optimice su inversión en la nube", "text": "Considere el uso de etiquetas de automatización para iniciar/detener máquinas virtuales en su entorno para ahorrar costos.", @@ -264,7 +290,8 @@ { "category": "Gobernanza", "guid": "29fd366b-a180-452b-9bd7-954b7700c667", - "link": "https://learn.microsoft.com/en-us/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", + "id": "B02.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", "severity": "Medio", "subcategory": "Optimice su inversión en la nube", "text": "Configure alertas de presupuesto \"reales\" y \"previstas\".", @@ -273,16 +300,18 @@ { "category": "Gestión de identidades y accesos", "guid": "4348bf81-7573-4512-8f46-9061cc198fea", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", + "id": "C01.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", "severity": "Alto", "subcategory": "Active Directory e identidad híbrida", "text": "Uso de identidades administradas en lugar de entidades de servicio para la autenticación en los servicios de Azure", - "training": "https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", "waf": "Seguridad" }, { "category": "Gestión de identidades y accesos", "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", + "id": "C02.01", "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "severity": "Medio", "subcategory": "Azure AD", @@ -292,6 +321,7 @@ { "category": "Gestión de identidades y accesos", "guid": "984a859c-773e-47d2-9162-3a765a917e1f", + "id": "C03.01", "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "severity": "Alto", "subcategory": "Identidad", @@ -302,16 +332,17 @@ { "category": "Gestión de identidades y accesos", "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "severity": "Medio", "subcategory": "Identidad", "text": "Integre los registros de Azure AD con Azure Monitor de plataforma central. Azure Monitor permite una única fuente de información sobre los datos de registro y supervisión en Azure, lo que brinda a las organizaciones opciones nativas en la nube para cumplir con los requisitos relacionados con la recopilación y retención de registros.", - "training": "", "waf": "Seguridad" }, { "category": "Gestión de identidades y accesos", "guid": "348ef254-c27d-442e-abba-c7571559ab91", + "id": "C03.03", "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "severity": "Alto", "subcategory": "Identidad", @@ -322,6 +353,7 @@ { "category": "Gestión de identidades y accesos", "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", + "id": "C03.04", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "severity": "Bajo", "subcategory": "Identidad", @@ -332,6 +364,7 @@ { "category": "Gestión de identidades y accesos", "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", + "id": "C03.05", "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "severity": "Alto", "subcategory": "Identidad", @@ -342,6 +375,7 @@ { "category": "Gestión de identidades y accesos", "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", + "id": "C03.06", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "severity": "Medio", "subcategory": "Identidad", @@ -352,6 +386,7 @@ { "category": "Gestión de identidades y accesos", "guid": "14658d35-58fd-4772-99b8-21112df27ee4", + "id": "C03.07", "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "severity": "Medio", "subcategory": "Identidad", @@ -362,6 +397,7 @@ { "category": "Gestión de identidades y accesos", "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", + "id": "C03.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", "severity": "Alto", "subcategory": "Identidad", @@ -372,6 +408,7 @@ { "category": "Gestión de identidades y accesos", "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", + "id": "C03.09", "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "severity": "Medio", "subcategory": "Identidad", @@ -382,6 +419,7 @@ { "category": "Gestión de identidades y accesos", "guid": "f5664b5e-984a-4859-a773-e7d261623a76", + "id": "C03.10", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "severity": "Medio", "subcategory": "Identidad", @@ -392,6 +430,7 @@ { "category": "Gestión de identidades y accesos", "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", + "id": "C03.11", "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "severity": "Medio", "subcategory": "Identidad", @@ -402,6 +441,7 @@ { "category": "Gestión de identidades y accesos", "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", + "id": "C03.12", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "Medio", "subcategory": "Identidad", @@ -412,6 +452,7 @@ { "category": "Gestión de identidades y accesos", "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", + "id": "C03.13", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "Medio", "subcategory": "Identidad", @@ -422,6 +463,7 @@ { "category": "Gestión de identidades y accesos", "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", + "id": "C03.14", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "severity": "Medio", "subcategory": "Identidad", @@ -432,6 +474,7 @@ { "category": "Gestión de identidades y accesos", "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", + "id": "C03.15", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "severity": "Medio", "subcategory": "Identidad", @@ -442,6 +485,7 @@ { "category": "Gestión de identidades y accesos", "guid": "35037e68-9349-4c15-b371-228514f4cdff", + "id": "C03.16", "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", "severity": "Medio", "subcategory": "Identidad", @@ -452,36 +496,39 @@ { "category": "Gestión de identidades y accesos", "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "id": "C04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "severity": "Bajo", "subcategory": "Zonas de aterrizaje", "text": "Configure la segmentación de red de identidad (ADDS) mediante el uso de una red virtual y vuelva al concentrador. Proporcionar autenticación dentro de la zona de aterrizaje de la aplicación (heredada).", - "training": "https://learn.microsoft.com/en-us/azure/architecture/example-scenario/identity/adds-extend-domain", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", "waf": "Seguridad" }, { "category": "Gestión de identidades y accesos", "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "id": "C04.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "severity": "Medio", "subcategory": "Zonas de aterrizaje", "text": "Use RBAC de Azure para administrar el acceso del plano de datos a los recursos, si es posible. Por ejemplo, operaciones de datos en Keyvault, cuenta de almacenamiento y servicios de base de datos. ", - "training": "https://learn.microsoft.com/en-us/azure/role-based-access-control/overview", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", "waf": "Seguridad" }, { "category": "Gestión de identidades y accesos", "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "id": "C04.03", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "severity": "Medio", "subcategory": "Zonas de aterrizaje", "text": "Use revisiones de acceso PIM de Azure AD para validar periódicamente los derechos de recursos.", - "training": "", "waf": "Seguridad" }, { "category": "Administración", "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", + "id": "D01.01", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -491,6 +538,7 @@ { "category": "Administración", "guid": "7f408960-c626-44cb-a018-347c8d790cdf", + "id": "D01.02", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -500,6 +548,7 @@ { "category": "Administración", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", + "id": "D02.01", "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "severity": "Medio", "subcategory": "Protección de datos", @@ -509,6 +558,7 @@ { "category": "Administración", "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", + "id": "D02.02", "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "severity": "Medio", "subcategory": "Protección de datos", @@ -518,6 +568,7 @@ { "category": "Administración", "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", + "id": "D03.01", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Medio", "subcategory": "Monitorización", @@ -528,6 +579,7 @@ { "category": "Administración", "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "D03.02", "severity": "Medio", "subcategory": "Monitorización", "text": "¿Está documentada la zona de aterrizaje?", @@ -536,7 +588,8 @@ { "category": "Administración", "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", - "link": "https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "severity": "Medio", "subcategory": "Monitorización", "text": "Use los registros de Azure Monitor cuando los requisitos de retención de registros superen los dos años. Actualmente puede mantener los datos en estado archivado durante un máximo de 7 años.", @@ -546,6 +599,7 @@ { "category": "Administración", "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", + "id": "D03.04", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Medio", "subcategory": "Monitorización", @@ -556,6 +610,7 @@ { "category": "Administración", "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", + "id": "D03.05", "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "severity": "Medio", "subcategory": "Monitorización", @@ -566,6 +621,7 @@ { "category": "Administración", "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", + "id": "D03.06", "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "severity": "Medio", "subcategory": "Monitorización", @@ -576,6 +632,7 @@ { "category": "Administración", "guid": "90483845-c986-4cb2-a131-56a12476e49f", + "id": "D03.07", "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "severity": "Medio", "subcategory": "Monitorización", @@ -586,6 +643,7 @@ { "category": "Administración", "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", + "id": "D03.08", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "severity": "Medio", "subcategory": "Monitorización", @@ -596,6 +654,7 @@ { "category": "Administración", "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", + "id": "D03.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Bajo", "subcategory": "Monitorización", @@ -605,6 +664,7 @@ { "category": "Administración", "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", + "id": "D03.10", "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", "severity": "Medio", "subcategory": "Monitorización", @@ -614,6 +674,7 @@ { "category": "Administración", "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", + "id": "D03.11", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "severity": "Medio", "subcategory": "Monitorización", @@ -623,6 +684,7 @@ { "category": "Administración", "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", + "id": "D03.12", "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "severity": "Medio", "subcategory": "Monitorización", @@ -632,6 +694,7 @@ { "category": "Administración", "guid": "9945bda4-3334-4f24-a116-34182ba52752", + "id": "D03.13", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Medio", "subcategory": "Monitorización", @@ -641,6 +704,7 @@ { "category": "Administración", "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", + "id": "D03.14", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "severity": "Medio", "subcategory": "Monitorización", @@ -650,6 +714,7 @@ { "category": "Administración", "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", + "id": "D03.15", "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "severity": "Medio", "subcategory": "Monitorización", @@ -659,6 +724,7 @@ { "category": "Administración", "guid": "97be9951-9048-4384-9c98-6cb2913156a1", + "id": "D03.16", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "severity": "Medio", "subcategory": "Monitorización", @@ -668,6 +734,7 @@ { "category": "Administración", "guid": "859c3900-4514-41eb-b010-475d695abd74", + "id": "D03.17", "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "severity": "Medio", "subcategory": "Monitorización", @@ -677,6 +744,7 @@ { "category": "Administración", "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", + "id": "D03.18", "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "severity": "Medio", "subcategory": "Monitorización", @@ -686,6 +754,7 @@ { "category": "Administración", "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", + "id": "D04.01", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "severity": "Medio", "subcategory": "Compromiso operacional", @@ -696,6 +765,7 @@ "category": "Administración", "description": "Las características de configuración de invitado de Azure Policy pueden auditar y corregir la configuración del equipo (por ejemplo, SO, aplicación, entorno) para garantizar que los recursos se alineen con las configuraciones esperadas, y Update Management puede aplicar la administración de revisiones para máquinas virtuales.", "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", + "id": "D04.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "severity": "Medio", "subcategory": "Compromiso operacional", @@ -705,6 +775,7 @@ { "category": "Administración", "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", + "id": "D05.01", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "severity": "Medio", "subcategory": "Proteger y recuperar", @@ -714,6 +785,7 @@ { "category": "Administración", "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", + "id": "D05.02", "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "severity": "Medio", "subcategory": "Proteger y recuperar", @@ -723,6 +795,7 @@ { "category": "Administración", "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", + "id": "D05.03", "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "severity": "Medio", "subcategory": "Proteger y recuperar", @@ -732,6 +805,7 @@ { "category": "Administración ", "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", + "id": "E01.01", "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "severity": "Alto", "subcategory": "Tolerancia a fallos", @@ -741,6 +815,7 @@ { "category": "Administración ", "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", + "id": "E01.02", "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "severity": "Alto", "subcategory": "Tolerancia a fallos", @@ -750,6 +825,7 @@ { "category": "Administración ", "guid": "84101f59-1941-4195-a270-e28034290e3a", + "id": "E01.03", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "Medio", "subcategory": "Tolerancia a fallos", @@ -759,6 +835,7 @@ { "category": "Administración ", "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", + "id": "E02.01", "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "severity": "Medio", "subcategory": "Escalabilidad", @@ -768,6 +845,7 @@ { "category": "Topología y conectividad de red", "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "F01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -777,6 +855,7 @@ { "category": "Topología y conectividad de red", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "F01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -788,6 +867,7 @@ "category": "Topología y conectividad de red", "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": "F01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -799,6 +879,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "F01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -809,6 +890,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "F01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -820,6 +902,7 @@ "category": "Topología y conectividad de red", "description": "La administración de proxies inversos en general y WAF en particular está más cerca de la aplicación que de la red, por lo que pertenecen a la misma suscripción que la aplicación. La centralización de Application Gateway y WAF en la suscripción de conectividad podría estar bien si está administrada por un solo equipo.", "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "F01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -830,6 +913,7 @@ { "category": "Topología y conectividad de red", "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "F01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -840,6 +924,7 @@ { "category": "Topología y conectividad de red", "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "F01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -850,6 +935,7 @@ { "category": "Topología y conectividad de red", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "F01.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -860,6 +946,7 @@ { "category": "Topología y conectividad de red", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "F01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -870,6 +957,7 @@ { "category": "Topología y conectividad de red", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "F01.11", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Bajo", "subcategory": "Entrega de aplicaciones", @@ -880,6 +968,7 @@ { "category": "Topología y conectividad de red", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "F01.12", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -891,6 +980,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "F01.13", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -900,6 +990,7 @@ { "category": "Topología y conectividad de red", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "F01.14", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -909,6 +1000,7 @@ { "category": "Topología y conectividad de red", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "F01.15", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -918,6 +1010,7 @@ { "category": "Topología y conectividad de red", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "F01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "Bajo", "subcategory": "Entrega de aplicaciones", @@ -927,6 +1020,7 @@ { "category": "Topología y conectividad de red", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "F01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -936,6 +1030,7 @@ { "category": "Topología y conectividad de red", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "F01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "Bajo", "subcategory": "Entrega de aplicaciones", @@ -946,6 +1041,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "F01.19", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -955,6 +1051,7 @@ { "category": "Topología y conectividad de red", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "F01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -964,6 +1061,7 @@ { "category": "Topología y conectividad de red", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "F01.21", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -973,6 +1071,7 @@ { "category": "Topología y conectividad de red", "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "id": "F02.01", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "Medio", "subcategory": "Encriptación", @@ -982,6 +1081,7 @@ { "category": "Topología y conectividad de red", "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "id": "F02.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "Bajo", "subcategory": "Encriptación", @@ -992,6 +1092,7 @@ { "category": "Topología y conectividad de red", "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", + "id": "F03.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", "severity": "Medio", "subcategory": "Hub and spoke", @@ -1002,6 +1103,7 @@ { "category": "Topología y conectividad de red", "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", + "id": "F03.02", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", "severity": "Alto", "subcategory": "Hub and spoke", @@ -1011,6 +1113,7 @@ { "category": "Topología y conectividad de red", "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", + "id": "F03.03", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", "severity": "Medio", "subcategory": "Hub and spoke", @@ -1020,6 +1123,7 @@ { "category": "Topología y conectividad de red", "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", + "id": "F03.04", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", "severity": "Bajo", "subcategory": "Hub and spoke", @@ -1030,6 +1134,7 @@ "category": "Topología y conectividad de red", "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": "F03.05", "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", "severity": "Bajo", "subcategory": "Hub and spoke", @@ -1039,6 +1144,7 @@ { "category": "Topología y conectividad de red", "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "id": "F03.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", "severity": "Medio", "subcategory": "Hub and spoke", @@ -1049,6 +1155,7 @@ { "category": "Topología y conectividad de red", "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", + "id": "F03.07", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", "severity": "Medio", "subcategory": "Hub and spoke", @@ -1060,6 +1167,7 @@ "category": "Topología y conectividad de red", "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": "F03.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", "severity": "Medio", "subcategory": "Hub and spoke", @@ -1070,6 +1178,7 @@ "category": "Topología y conectividad de red", "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": "F03.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", "severity": "Medio", "subcategory": "Hub and spoke", @@ -1080,6 +1189,7 @@ "category": "Topología y conectividad de red", "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": "F03.10", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", "severity": "Alto", "subcategory": "Hub and spoke", @@ -1089,6 +1199,7 @@ { "category": "Topología y conectividad de red", "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", + "id": "F04.01", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", "severity": "Medio", "subcategory": "Híbrido", @@ -1100,6 +1211,7 @@ "category": "Topología y conectividad de red", "description": "Puede usar los pesos de conexión y pendientes de ruta para influir en el tráfico de Azure al local, y toda la gama de atributos BGP en sus propios enrutadores para influir en el tráfico del entorno local a Azure.", "guid": "f29812b2-363c-4efe-879b-599de0d5973c", + "id": "F04.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "Medio", "subcategory": "Híbrido", @@ -1111,6 +1223,7 @@ "category": "Topología y conectividad de red", "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": "F04.03", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "Medio", "subcategory": "Híbrido", @@ -1122,6 +1235,7 @@ "category": "Topología y conectividad de red", "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": "F04.04", "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", "severity": "Alto", "subcategory": "Híbrido", @@ -1132,6 +1246,7 @@ "category": "Topología y conectividad de red", "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": "F04.05", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", "severity": "Alto", "subcategory": "Híbrido", @@ -1142,6 +1257,7 @@ "category": "Topología y conectividad de red", "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": "F04.06", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", "severity": "Medio", "subcategory": "Híbrido", @@ -1152,6 +1268,7 @@ { "category": "Topología y conectividad de red", "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", + "id": "F04.07", "link": "https://learn.microsoft.com/azure/networking/", "severity": "Medio", "subcategory": "Híbrido", @@ -1162,6 +1279,7 @@ { "category": "Topología y conectividad de red", "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", + "id": "F04.08", "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", "severity": "Medio", "subcategory": "Híbrido", @@ -1173,6 +1291,7 @@ "category": "Topología y conectividad de red", "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": "F04.09", "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", "severity": "Medio", "subcategory": "Híbrido", @@ -1183,6 +1302,7 @@ { "category": "Topología y conectividad de red", "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "id": "F04.10", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "Alto", "subcategory": "Híbrido", @@ -1193,6 +1313,7 @@ { "category": "Topología y conectividad de red", "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "id": "F04.11", "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", "severity": "Medio", "subcategory": "Híbrido", @@ -1203,6 +1324,7 @@ { "category": "Topología y conectividad de red", "guid": "b30e38c3-f298-412b-8363-cefe179b599d", + "id": "F04.12", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", "severity": "Medio", "subcategory": "Híbrido", @@ -1213,6 +1335,7 @@ { "category": "Topología y conectividad de red", "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", + "id": "F04.13", "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", "severity": "Medio", "subcategory": "Híbrido", @@ -1223,6 +1346,7 @@ { "category": "Topología y conectividad de red", "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", + "id": "F04.14", "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", "severity": "Medio", "subcategory": "Híbrido", @@ -1233,6 +1357,7 @@ { "category": "Topología y conectividad de red", "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "id": "F04.15", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", "severity": "Alto", "subcategory": "Híbrido", @@ -1242,6 +1367,7 @@ { "category": "Topología y conectividad de red", "guid": "558fd772-49b8-4211-82df-27ee412e7f98", + "id": "F05.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "Alto", "subcategory": "Plan IP", @@ -1253,6 +1379,7 @@ "category": "Topología y conectividad de red", "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": "F05.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "Bajo", "subcategory": "Plan IP", @@ -1264,6 +1391,7 @@ "category": "Topología y conectividad de red", "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": "F05.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "Alto", "subcategory": "Plan IP", @@ -1274,6 +1402,7 @@ { "category": "Topología y conectividad de red", "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", + "id": "F05.04", "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", "severity": "Alto", "subcategory": "Plan IP", @@ -1284,6 +1413,7 @@ { "category": "Topología y conectividad de red", "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", + "id": "F05.05", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "Medio", "subcategory": "Plan IP", @@ -1294,6 +1424,7 @@ { "category": "Topología y conectividad de red", "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", + "id": "F05.06", "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", "severity": "Medio", "subcategory": "Plan IP", @@ -1304,6 +1435,7 @@ { "category": "Topología y conectividad de red", "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", + "id": "F05.07", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "Bajo", "subcategory": "Plan IP", @@ -1313,6 +1445,7 @@ { "category": "Topología y conectividad de red", "guid": "614658d3-558f-4d77-849b-821112df27ee", + "id": "F05.08", "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", "severity": "Alto", "subcategory": "Plan IP", @@ -1323,6 +1456,7 @@ { "category": "Topología y conectividad de red", "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "id": "F06.01", "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", "severity": "Medio", "subcategory": "Internet", @@ -1333,7 +1467,8 @@ "category": "Topología y conectividad de red", "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", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet", "severity": "Medio", "subcategory": "Internet", "text": "Use Azure Bastion en una subred /26 o superior.", @@ -1342,6 +1477,7 @@ { "category": "Topología y conectividad de red", "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", + "id": "F06.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Alto", "subcategory": "Internet", @@ -1352,6 +1488,7 @@ { "category": "Topología y conectividad de red", "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", + "id": "F06.04", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "Medio", "subcategory": "Internet", @@ -1362,6 +1499,7 @@ { "category": "Topología y conectividad de red", "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", + "id": "F06.05", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "Bajo", "subcategory": "Internet", @@ -1372,6 +1510,7 @@ { "category": "Topología y conectividad de red", "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", + "id": "F06.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "severity": "Medio", "subcategory": "Internet", @@ -1382,6 +1521,7 @@ { "category": "Topología y conectividad de red", "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", + "id": "F06.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Bajo", "subcategory": "Internet", @@ -1392,6 +1532,7 @@ { "category": "Topología y conectividad de red", "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", + "id": "F06.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Alto", "subcategory": "Internet", @@ -1402,6 +1543,7 @@ { "category": "Topología y conectividad de red", "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", + "id": "F06.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", "severity": "Alto", "subcategory": "Internet", @@ -1413,6 +1555,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "id": "F06.10", "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", "severity": "Alto", "subcategory": "Internet", @@ -1423,6 +1566,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "id": "F06.11", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "Alto", "subcategory": "Internet", @@ -1433,6 +1577,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "id": "F06.12", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "Alto", "subcategory": "Internet", @@ -1443,6 +1588,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "id": "F06.13", "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", "severity": "Alto", "subcategory": "Internet", @@ -1453,6 +1599,7 @@ "category": "Topología y conectividad de red", "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": "F06.14", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "severity": "Alto", "subcategory": "Internet", @@ -1462,6 +1609,7 @@ { "category": "Topología y conectividad de red", "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "F07.01", "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "severity": "Alto", "subcategory": "Paas", @@ -1472,6 +1620,7 @@ { "category": "Topología y conectividad de red", "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", + "id": "F07.02", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Medio", "subcategory": "Paas", @@ -1482,6 +1631,7 @@ { "category": "Topología y conectividad de red", "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", + "id": "F07.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Medio", "subcategory": "Paas", @@ -1493,6 +1643,7 @@ "category": "Topología y conectividad de red", "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": "F07.04", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Medio", "subcategory": "Paas", @@ -1503,6 +1654,7 @@ { "category": "Topología y conectividad de red", "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", + "id": "F07.05", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Medio", "subcategory": "Paas", @@ -1514,6 +1666,7 @@ "category": "Topología y conectividad de red", "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": "F08.01", "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", "severity": "Alto", "subcategory": "Segmentación", @@ -1524,6 +1677,7 @@ "category": "Topología y conectividad de red", "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": "F08.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", "severity": "Alto", "subcategory": "Segmentación", @@ -1534,6 +1688,7 @@ "category": "Topología y conectividad de red", "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": "F08.03", "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", "severity": "Medio", "subcategory": "Segmentación", @@ -1543,6 +1698,7 @@ { "category": "Topología y conectividad de red", "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", + "id": "F08.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", "severity": "Medio", "subcategory": "Segmentación", @@ -1553,6 +1709,7 @@ { "category": "Topología y conectividad de red", "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", + "id": "F08.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Medio", "subcategory": "Segmentación", @@ -1564,6 +1721,7 @@ "category": "Topología y conectividad de red", "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": "F08.06", "severity": "Medio", "subcategory": "Segmentación", "text": "El equipo de aplicaciones debe usar grupos de seguridad de aplicaciones en los grupos de seguridad de red de nivel de subred para ayudar a proteger las máquinas virtuales de varios niveles dentro de la zona de aterrizaje.", @@ -1573,6 +1731,7 @@ { "category": "Topología y conectividad de red", "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", + "id": "F08.07", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "Medio", "subcategory": "Segmentación", @@ -1583,6 +1742,7 @@ { "category": "Topología y conectividad de red", "guid": "dfe237de-143b-416c-91d7-aa9b64704489", + "id": "F08.08", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "Medio", "subcategory": "Segmentación", @@ -1593,6 +1753,7 @@ { "category": "Topología y conectividad de red", "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", + "id": "F09.01", "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1603,6 +1764,7 @@ { "category": "Topología y conectividad de red", "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", + "id": "F09.02", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1612,6 +1774,7 @@ { "category": "Topología y conectividad de red", "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", + "id": "F09.03", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "Bajo", "subcategory": "Virtual WAN", @@ -1622,6 +1785,7 @@ "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", + "id": "F09.04", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1632,6 +1796,7 @@ { "category": "Topología y conectividad de red", "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "id": "F09.05", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1641,6 +1806,7 @@ { "category": "Topología y conectividad de red", "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "id": "F09.06", "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1650,6 +1816,7 @@ { "category": "Topología y conectividad de red", "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "id": "F09.07", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1659,6 +1826,7 @@ { "category": "Topología y conectividad de red", "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "id": "F09.08", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1668,6 +1836,7 @@ { "category": "Topología y conectividad de red", "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "id": "F09.09", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", "severity": "Medio", "subcategory": "Virtual WAN", @@ -1677,6 +1846,7 @@ { "category": "Topología y conectividad de red", "guid": "9c75dfef-573c-461c-a698-68598595581a", + "id": "F09.10", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", "severity": "Alto", "subcategory": "Virtual WAN", @@ -1686,6 +1856,7 @@ { "category": "Topología y conectividad de red", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "G01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -1695,6 +1866,7 @@ { "category": "Topología y conectividad de red", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "G01.02", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -1704,6 +1876,7 @@ { "category": "Topología y conectividad de red", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "G01.03", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -1713,6 +1886,7 @@ { "category": "Topología y conectividad de red", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "G01.04", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -1722,6 +1896,7 @@ { "category": "Topología y conectividad de red", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "G01.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -1731,6 +1906,7 @@ { "category": "Topología y conectividad de red", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "G01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -1740,6 +1916,7 @@ { "category": "Topología y conectividad de red", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "G01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "Alto", "subcategory": "Entrega de aplicaciones", @@ -1749,6 +1926,7 @@ { "category": "Topología y conectividad de red", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "G01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -1758,6 +1936,7 @@ { "category": "Topología y conectividad de red", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "G01.09", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -1767,6 +1946,7 @@ { "category": "Topología y conectividad de red", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "G01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -1776,6 +1956,7 @@ { "category": "Topología y conectividad de red", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "G01.11", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "Bajo", "subcategory": "Entrega de aplicaciones", @@ -1785,6 +1966,7 @@ { "category": "Topología y conectividad de red", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "G01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "Medio", "subcategory": "Entrega de aplicaciones", @@ -1794,7 +1976,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", "severity": "Alto", "subcategory": "Topologías de equipo de DevOps", "text": "Asegúrese de contar con un equipo de plataforma de DevOps multifuncional para crear, administrar y mantener su arquitectura de Azure Landing Zone.", @@ -1803,7 +1986,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "Bajo", "subcategory": "Topologías de equipo de DevOps", "text": "Objetivo de definir funciones para el equipo de Azure Landing Zone Platform.", @@ -1812,7 +1996,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "Bajo", "subcategory": "Topologías de equipo de DevOps", "text": "Intente definir funciones para que los equipos de carga de trabajo de aplicaciones sean autosuficientes y no requieran el soporte del equipo de la plataforma DevOps. Logre esto mediante el uso del rol RBAC personalizado.", @@ -1821,7 +2006,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "165eb5e9-b434-448a-9e24-178632186212", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H01.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "Alto", "subcategory": "Topologías de equipo de DevOps", "text": "Use una canalización de CI/CD para implementar artefactos de IaC y garantizar la calidad de la implementación y de los entornos de Azure.", @@ -1830,7 +2016,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "Medio", "subcategory": "Topologías de equipo de DevOps", "text": "Incluya pruebas unitarias para IaC y código de aplicación como parte del proceso de compilación.", @@ -1839,7 +2026,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "Alto", "subcategory": "Topologías de equipo de DevOps", "text": "Use los secretos del Almacén de claves para evitar codificar información confidencial, como credenciales (contraseñas de usuario de máquinas virtuales), certificados o claves.", @@ -1848,7 +2036,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", "severity": "Bajo", "subcategory": "Topologías de equipo de DevOps", "text": "Implemente la automatización para File > New > Landing Zone para aplicaciones y cargas de trabajo.", @@ -1857,7 +2046,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "Alto", "subcategory": "Ciclo de vida de desarrollo", "text": "Asegúrese de que se utiliza un sistema de control de versiones para el código fuente de las aplicaciones y se desarrolla IaC. Microsoft recomienda Git.", @@ -1866,7 +2056,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "Bajo", "subcategory": "Ciclo de vida de desarrollo", "text": "Siga una estrategia de bifurcación para permitir que los equipos colaboren mejor y administren de manera eficiente el control de versiones de IaC y el código de la aplicación. Revisa opciones como Github Flow.", @@ -1875,7 +2066,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "Medio", "subcategory": "Ciclo de vida de desarrollo", "text": "Adopte una estrategia de solicitud de extracción para ayudar a mantener el control de los cambios de código combinados en ramas.", @@ -1884,7 +2076,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "Alto", "subcategory": "Estrategia de desarrollo", "text": "Aproveche la infraestructura declarativa como herramientas de código como Azure Bicep, plantillas ARM o Terraform para crear y mantener su arquitectura de Azure Landing Zone. Tanto desde la perspectiva de la carga de trabajo de la plataforma como de la aplicación.", @@ -1893,7 +2086,8 @@ { "category": "Automatización de plataformas y DevOps", "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", + "id": "H04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", "severity": "Alto", "subcategory": "Seguridad", "text": " Integrar la seguridad en el proceso ya combinado de desarrollo y operaciones en DevOps para mitigar los riesgos en el proceso de innovación.", @@ -1902,6 +2096,7 @@ { "category": "Organización de recursos", "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", + "id": "I01.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", "severity": "Alto", "subcategory": "Nomenclatura y etiquetado", @@ -1912,6 +2107,7 @@ "category": "Organización de recursos", "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": "I02.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "Medio", "subcategory": "Suscripciones", @@ -1923,6 +2119,7 @@ "category": "Organización de recursos", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", + "id": "I02.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", "severity": "Medio", "subcategory": "Suscripciones", @@ -1933,6 +2130,7 @@ { "category": "Organización de recursos", "guid": "667313b4-f566-44b5-b984-a859c773e7d2", + "id": "I02.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "Medio", "subcategory": "Suscripciones", @@ -1943,6 +2141,7 @@ { "category": "Organización de recursos", "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", + "id": "I02.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "Medio", "subcategory": "Suscripciones", @@ -1953,6 +2152,7 @@ { "category": "Organización de recursos", "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", + "id": "I02.05", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "Medio", "subcategory": "Suscripciones", @@ -1964,6 +2164,7 @@ "category": "Organización de recursos", "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": "I02.06", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", "severity": "Medio", "subcategory": "Suscripciones", @@ -1973,6 +2174,7 @@ { "category": "Organización de recursos", "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", + "id": "I02.07", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "severity": "Medio", "subcategory": "Suscripciones", @@ -1982,6 +2184,7 @@ { "category": "Organización de recursos", "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", + "id": "I02.08", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "Medio", "subcategory": "Suscripciones", @@ -1991,6 +2194,7 @@ { "category": "Organización de recursos", "guid": "49b82111-2df2-47ee-912e-7f983f630472", + "id": "I02.09", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "Alto", "subcategory": "Suscripciones", @@ -2000,6 +2204,7 @@ { "category": "Organización de recursos", "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", + "id": "I02.10", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "Medio", "subcategory": "Suscripciones", @@ -2009,6 +2214,7 @@ { "category": "Organización de recursos", "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", + "id": "I02.11", "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", "severity": "Alto", "subcategory": "Suscripciones", @@ -2019,6 +2225,7 @@ { "category": "Organización de recursos", "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", + "id": "I02.12", "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", "severity": "Alto", "subcategory": "Suscripciones", @@ -2029,6 +2236,7 @@ { "category": "Organización de recursos", "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "I02.13", "link": "https://azure.microsoft.com/global-infrastructure/services/", "severity": "Medio", "subcategory": "Suscripciones", @@ -2039,6 +2247,7 @@ { "category": "Organización de recursos", "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "I02.14", "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", "severity": "Alto", "subcategory": "Suscripciones", @@ -2049,6 +2258,7 @@ { "category": "Organización de recursos", "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "I02.15", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "Medio", "subcategory": "Suscripciones", @@ -2060,6 +2270,7 @@ "category": "Organización de recursos", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", + "id": "I02.16", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", "severity": "Medio", "subcategory": "Suscripciones", @@ -2070,6 +2281,7 @@ { "category": "Seguridad", "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", + "id": "J01.01", "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "severity": "Medio", "subcategory": "Control de acceso", @@ -2079,6 +2291,7 @@ { "category": "Seguridad", "guid": "01365d38-e43f-49cc-ad86-8266abca264f", + "id": "J01.02", "link": "https://www.microsoft.com/security/business/zero-trust", "severity": "Medio", "subcategory": "Control de acceso", @@ -2088,6 +2301,7 @@ { "category": "Seguridad", "guid": "5017f154-e3ab-4369-9829-e7e316183687", + "id": "J02.01", "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "severity": "Alto", "subcategory": "Cifrado y claves", @@ -2098,6 +2312,7 @@ "category": "Seguridad", "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": "J02.02", "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2107,6 +2322,7 @@ { "category": "Seguridad", "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", + "id": "J02.03", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2116,6 +2332,7 @@ { "category": "Seguridad", "guid": "dc055bcf-619e-48a1-9f98-879525d62688", + "id": "J02.04", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2125,6 +2342,7 @@ { "category": "Seguridad", "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "J02.05", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2134,6 +2352,7 @@ { "category": "Seguridad", "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "J02.06", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2143,6 +2362,7 @@ { "category": "Seguridad", "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", + "id": "J02.07", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2152,6 +2372,7 @@ { "category": "Seguridad", "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", + "id": "J02.08", "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2161,6 +2382,7 @@ { "category": "Seguridad", "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", + "id": "J02.09", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2170,6 +2392,7 @@ { "category": "Seguridad", "guid": "16183687-a047-47a2-8994-5bda43334f24", + "id": "J02.10", "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2179,6 +2402,7 @@ { "category": "Seguridad", "guid": "91163418-2ba5-4275-8694-4008be7d7e48", + "id": "J02.11", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2188,6 +2412,7 @@ { "category": "Seguridad", "guid": "25d62688-6d70-4ba6-a97b-e99519048384", + "id": "J02.12", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Medio", "subcategory": "Cifrado y claves", @@ -2197,6 +2422,7 @@ { "category": "Seguridad", "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", + "id": "J03.01", "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "severity": "Medio", "subcategory": "Operaciones", @@ -2206,6 +2432,7 @@ { "category": "Seguridad", "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", + "id": "J03.02", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "severity": "Medio", "subcategory": "Operaciones", @@ -2215,15 +2442,47 @@ { "category": "Seguridad", "guid": "09945bda-4333-44f2-9911-634182ba5275", - "link": "https://learn.microsoft.com/azure/security-center/", - "severity": "Medio", + "id": "J03.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", + "severity": "Alto", + "subcategory": "Operaciones", + "text": "Habilite Defender Cloud Security Posture Management para todas las suscripciones.", + "waf": "Seguridad" + }, + { + "category": "Seguridad", + "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", + "id": "J03.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", + "severity": "Alto", + "subcategory": "Operaciones", + "text": "Habilite un plan de protección de cargas de trabajo en la nube de Defender para servidores en todas las suscripciones.", + "waf": "Seguridad" + }, + { + "category": "Seguridad", + "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", + "id": "J03.05", + "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", + "severity": "Alto", + "subcategory": "Operaciones", + "text": "Habilite los planes de protección de cargas de trabajo en la nube de Defender para recursos de Azure en todas las suscripciones.", + "waf": "Seguridad" + }, + { + "category": "Seguridad", + "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", + "id": "J03.06", + "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection", + "severity": "Alto", "subcategory": "Operaciones", - "text": "Habilite Defender for Cloud Standard para todas las suscripciones.", + "text": "Habilite Endpoint Protection en servidores IaaS.", "waf": "Seguridad" }, { "category": "Seguridad", "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "J03.07", "link": "https://learn.microsoft.com/azure/security-center/", "severity": "Medio", "subcategory": "Operaciones", @@ -2233,6 +2492,7 @@ { "category": "Seguridad", "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", + "id": "J03.08", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Medio", "subcategory": "Operaciones", @@ -2242,6 +2502,7 @@ { "category": "Seguridad", "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", + "id": "J04.01", "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", "severity": "Alto", "subcategory": "Visión general", @@ -2251,6 +2512,7 @@ { "category": "Seguridad", "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", + "id": "J04.02", "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", "severity": "Alto", "subcategory": "Visión general", @@ -2260,16 +2522,17 @@ { "category": "Seguridad", "guid": "6f704104-85c1-441f-96d3-c9819911645e", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/roles/security-planning", + "id": "J05.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning", "severity": "Alto", "subcategory": "Acceso privilegiado seguro", "text": "Cuentas de administrador privilegiadas independientes para las tareas administrativas de Azure.", - "training": "", "waf": "Seguridad" }, { "category": "Seguridad", "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", + "id": "J06.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "Medio", "subcategory": "Marco de habilitación de servicios", @@ -2279,6 +2542,7 @@ { "category": "Seguridad", "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", + "id": "J06.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "Medio", "subcategory": "Marco de habilitación de servicios", @@ -2289,7 +2553,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "September 07, 2023" + "timestamp": "September 14, 2023" }, "severities": [ { diff --git a/checklists/alz_checklist.ja.json b/checklists/alz_checklist.ja.json index a0d7dc949..6badd0274 100644 --- a/checklists/alz_checklist.ja.json +++ b/checklists/alz_checklist.ja.json @@ -29,17 +29,19 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", - "link": "https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/considerations/tenancy-models", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations", "severity": "中程度", "subcategory": "Azure AD テナント", - "text": "いくつの Azure AD テナントを管理していますか?", + "text": "マルチテナントの明確な規制要件またはビジネス要件がない限り、Azure リソースの管理には 1 つの Entra テナントを使用します。", "waf": "オペレーションズ" }, { "category": "Azure Billing and Active Directory テナント", "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", - "severity": "中程度", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", + "severity": "低い", "subcategory": "Azure AD テナント", "text": "Azure AD テナントを管理するためのマルチテナント自動化アプローチがあることを確認する", "waf": "オペレーションズ" @@ -47,8 +49,9 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", - "severity": "中程度", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "severity": "低い", "subcategory": "Azure AD テナント", "text": "マルチテナント管理のための Azure Lighthouse の活用", "waf": "オペレーションズ" @@ -56,7 +59,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "中程度", "subcategory": "クラウドソリューションプロバイダー", "text": "パートナーによるテナントの管理に Azure Lighthouse が使用されていることを確認します", @@ -65,7 +69,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "低い", "subcategory": "クラウドソリューションプロバイダー", "text": "CSP パートナーとサポート要求とエスカレーション プロセスについて話し合う", @@ -74,7 +79,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "32952499-58c8-4e6f-ada5-972e67893d55", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "中程度", "subcategory": "クラウドソリューションプロバイダー", "text": "Azure コスト管理を使用したコスト レポートとビューのセットアップ", @@ -83,7 +89,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "severity": "中程度", "subcategory": "エンタープライズ契約", "text": "通知用連絡先をグループ メールボックスに構成する", @@ -92,7 +99,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "低い", "subcategory": "エンタープライズ契約", "text": "部門とアカウントを使用して組織の構造を登録階層にマップすると、課金を分離するのに役立ちます。", @@ -101,7 +109,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "高い", "subcategory": "エンタープライズ契約", "text": "アカウントの種類が \"職場と学校アカウント\" に構成されていることを確認します", @@ -110,7 +119,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "中程度", "subcategory": "エンタープライズ契約", "text": "EA 登録で DA ビュー料金と AO ビュー料金の両方を有効にして、ユーザーが正しい権限でコストと請求データを確認できるようにします。", @@ -119,7 +129,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "低い", "subcategory": "エンタープライズ契約", "text": "エンタープライズ開発/テスト サブスクリプションを利用して、非運用ワークロードのコストを削減する", @@ -128,7 +139,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "中程度", "subcategory": "エンタープライズ契約", "text": "ロールの割り当てを定期的に監査して、マイクロソフト エンタープライズ契約の登録にアクセスできるユーザーを確認する", @@ -137,7 +149,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "低い", "subcategory": "マイクロソフト クラウド契約", "text": "契約の課金アカウント通知の連絡先メールを構成する", @@ -146,7 +159,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/mca-section-invoice", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "severity": "低い", "subcategory": "マイクロソフト クラウド契約", "text": "[課金プロファイル] セクションと [請求書] セクションを使用して、効果的なコスト管理のための契約請求を構成します", @@ -155,7 +169,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "低い", "subcategory": "マイクロソフト クラウド契約", "text": "Azure プランを利用して、非運用ワークロードのコストを削減する", @@ -164,7 +179,8 @@ { "category": "Azure Billing and Active Directory テナント", "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "中程度", "subcategory": "マイクロソフト クラウド契約", "text": "契約請求 RBAC ロールの割り当てを定期的に監査して、MCA 請求アカウントにアクセスできるユーザーを確認する", @@ -173,6 +189,7 @@ { "category": "統治", "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", + "id": "B01.01", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "高い", "subcategory": "統治", @@ -182,6 +199,7 @@ { "category": "統治", "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", + "id": "B01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", "severity": "中程度", "subcategory": "統治", @@ -191,6 +209,7 @@ { "category": "統治", "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", + "id": "B01.03", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "中程度", "subcategory": "統治", @@ -200,6 +219,7 @@ { "category": "統治", "guid": "223ace8c-b123-408c-a501-7f154e3ab369", + "id": "B01.04", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "中程度", "subcategory": "統治", @@ -209,6 +229,7 @@ { "category": "統治", "guid": "3829e7e3-1618-4368-9a04-77a209945bda", + "id": "B01.05", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "中程度", "subcategory": "統治", @@ -218,6 +239,7 @@ { "category": "統治", "guid": "43334f24-9116-4341-a2ba-527526944008", + "id": "B01.06", "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "severity": "低い", "subcategory": "統治", @@ -227,6 +249,7 @@ { "category": "統治", "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", + "id": "B01.07", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "中程度", "subcategory": "統治", @@ -237,6 +260,7 @@ "category": "統治", "description": "リソース ポリシー共同作成者の役割を特定のスコープに割り当てると、ポリシー管理を関連するチームに委任できます。たとえば、中央の IT チームが管理グループ レベルのポリシーを監督し、アプリケーション チームがサブスクリプションのポリシーを処理して、組織の標準に準拠した分散ガバナンスを実現できます。", "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", + "id": "B01.08", "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "severity": "中程度", "subcategory": "統治", @@ -246,6 +270,7 @@ { "category": "統治", "guid": "19048384-5c98-46cb-8913-156a12476e49", + "id": "B01.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "中程度", "subcategory": "統治", @@ -255,7 +280,8 @@ { "category": "統治", "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", - "link": "https://learn.microsoft.com/en-us/azure/automation/automation-solution-vm-management-config", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "severity": "低い", "subcategory": "クラウドへの投資を最適化する", "text": "コストを節約するために、自動化タグを使用して環境内の VM を起動/停止することを検討してください。", @@ -264,7 +290,8 @@ { "category": "統治", "guid": "29fd366b-a180-452b-9bd7-954b7700c667", - "link": "https://learn.microsoft.com/en-us/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", + "id": "B02.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", "severity": "中程度", "subcategory": "クラウドへの投資を最適化する", "text": "「実績」および「予測」予算アラートを設定します。", @@ -273,16 +300,18 @@ { "category": "ID およびアクセス管理", "guid": "4348bf81-7573-4512-8f46-9061cc198fea", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", + "id": "C01.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", "severity": "高い", "subcategory": "アクティブ ディレクトリとハイブリッド ID", "text": "Azure サービスに対する認証にサービス プリンシパルの代わりにマネージド ID を使用する", - "training": "https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", "waf": "安全" }, { "category": "ID およびアクセス管理", "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", + "id": "C02.01", "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "severity": "中程度", "subcategory": "Azure AD", @@ -292,6 +321,7 @@ { "category": "ID およびアクセス管理", "guid": "984a859c-773e-47d2-9162-3a765a917e1f", + "id": "C03.01", "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "severity": "高い", "subcategory": "同一性", @@ -302,16 +332,17 @@ { "category": "ID およびアクセス管理", "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "severity": "中程度", "subcategory": "同一性", "text": "Azure AD ログをプラットフォーム中心の Azure Monitor と統合します。Azure Monitor を使用すると、Azure のログと監視データに関する信頼できる唯一の情報源を使用できるため、ログの収集と保持に関する要件を満たすためのクラウド ネイティブ オプションを組織に提供します。", - "training": "", "waf": "安全" }, { "category": "ID およびアクセス管理", "guid": "348ef254-c27d-442e-abba-c7571559ab91", + "id": "C03.03", "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "severity": "高い", "subcategory": "同一性", @@ -322,6 +353,7 @@ { "category": "ID およびアクセス管理", "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", + "id": "C03.04", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "severity": "低い", "subcategory": "同一性", @@ -332,6 +364,7 @@ { "category": "ID およびアクセス管理", "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", + "id": "C03.05", "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "severity": "高い", "subcategory": "同一性", @@ -342,6 +375,7 @@ { "category": "ID およびアクセス管理", "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", + "id": "C03.06", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "severity": "中程度", "subcategory": "同一性", @@ -352,6 +386,7 @@ { "category": "ID およびアクセス管理", "guid": "14658d35-58fd-4772-99b8-21112df27ee4", + "id": "C03.07", "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "severity": "中程度", "subcategory": "同一性", @@ -362,6 +397,7 @@ { "category": "ID およびアクセス管理", "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", + "id": "C03.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", "severity": "高い", "subcategory": "同一性", @@ -372,6 +408,7 @@ { "category": "ID およびアクセス管理", "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", + "id": "C03.09", "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "severity": "中程度", "subcategory": "同一性", @@ -382,6 +419,7 @@ { "category": "ID およびアクセス管理", "guid": "f5664b5e-984a-4859-a773-e7d261623a76", + "id": "C03.10", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "severity": "中程度", "subcategory": "同一性", @@ -392,6 +430,7 @@ { "category": "ID およびアクセス管理", "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", + "id": "C03.11", "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "severity": "中程度", "subcategory": "同一性", @@ -402,6 +441,7 @@ { "category": "ID およびアクセス管理", "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", + "id": "C03.12", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "中程度", "subcategory": "同一性", @@ -412,6 +452,7 @@ { "category": "ID およびアクセス管理", "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", + "id": "C03.13", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "中程度", "subcategory": "同一性", @@ -422,6 +463,7 @@ { "category": "ID およびアクセス管理", "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", + "id": "C03.14", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "severity": "中程度", "subcategory": "同一性", @@ -432,6 +474,7 @@ { "category": "ID およびアクセス管理", "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", + "id": "C03.15", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "severity": "中程度", "subcategory": "同一性", @@ -442,6 +485,7 @@ { "category": "ID およびアクセス管理", "guid": "35037e68-9349-4c15-b371-228514f4cdff", + "id": "C03.16", "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", "severity": "中程度", "subcategory": "同一性", @@ -452,36 +496,39 @@ { "category": "ID およびアクセス管理", "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "id": "C04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "severity": "低い", "subcategory": "ランディング ゾーン", "text": "仮想ネットワークを使用して ID (ADDS) ネットワーク セグメント化を構成し、ハブにピアバックします。アプリケーション ランディング ゾーン (レガシ) 内で認証を提供する。", - "training": "https://learn.microsoft.com/en-us/azure/architecture/example-scenario/identity/adds-extend-domain", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", "waf": "安全" }, { "category": "ID およびアクセス管理", "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "id": "C04.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "severity": "中程度", "subcategory": "ランディング ゾーン", "text": "可能であれば、Azure RBAC を使用して、リソースへのデータ プレーン アクセスを管理します。たとえば、Keyvault、ストレージ アカウント、データベース サービス全体のデータ操作。", - "training": "https://learn.microsoft.com/en-us/azure/role-based-access-control/overview", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", "waf": "安全" }, { "category": "ID およびアクセス管理", "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "id": "C04.03", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "severity": "中程度", "subcategory": "ランディング ゾーン", "text": "Azure AD PIM アクセス レビューを使用して、リソースの権利を定期的に検証します。", - "training": "", "waf": "安全" }, { "category": "管理", "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", + "id": "D01.01", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "severity": "高い", "subcategory": "アプリ配信", @@ -491,6 +538,7 @@ { "category": "管理", "guid": "7f408960-c626-44cb-a018-347c8d790cdf", + "id": "D01.02", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "severity": "中程度", "subcategory": "アプリ配信", @@ -500,6 +548,7 @@ { "category": "管理", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", + "id": "D02.01", "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "severity": "中程度", "subcategory": "データ保護", @@ -509,6 +558,7 @@ { "category": "管理", "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", + "id": "D02.02", "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "severity": "中程度", "subcategory": "データ保護", @@ -518,6 +568,7 @@ { "category": "管理", "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", + "id": "D03.01", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "中程度", "subcategory": "モニタリング", @@ -528,6 +579,7 @@ { "category": "管理", "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "D03.02", "severity": "中程度", "subcategory": "モニタリング", "text": "ランディング ゾーンは文書化されていますか?", @@ -536,7 +588,8 @@ { "category": "管理", "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", - "link": "https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "severity": "中程度", "subcategory": "モニタリング", "text": "Azure Monitor ログは、ログの保有期間の要件が 2 年を超える場合に使用します。現在、データをアーカイブ状態で最大 7 年間保持できます。", @@ -546,6 +599,7 @@ { "category": "管理", "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", + "id": "D03.04", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "中程度", "subcategory": "モニタリング", @@ -556,6 +610,7 @@ { "category": "管理", "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", + "id": "D03.05", "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "severity": "中程度", "subcategory": "モニタリング", @@ -566,6 +621,7 @@ { "category": "管理", "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", + "id": "D03.06", "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "severity": "中程度", "subcategory": "モニタリング", @@ -576,6 +632,7 @@ { "category": "管理", "guid": "90483845-c986-4cb2-a131-56a12476e49f", + "id": "D03.07", "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "severity": "中程度", "subcategory": "モニタリング", @@ -586,6 +643,7 @@ { "category": "管理", "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", + "id": "D03.08", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "severity": "中程度", "subcategory": "モニタリング", @@ -596,6 +654,7 @@ { "category": "管理", "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", + "id": "D03.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "低い", "subcategory": "モニタリング", @@ -605,6 +664,7 @@ { "category": "管理", "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", + "id": "D03.10", "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", "severity": "中程度", "subcategory": "モニタリング", @@ -614,6 +674,7 @@ { "category": "管理", "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", + "id": "D03.11", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "severity": "中程度", "subcategory": "モニタリング", @@ -623,6 +684,7 @@ { "category": "管理", "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", + "id": "D03.12", "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "severity": "中程度", "subcategory": "モニタリング", @@ -632,6 +694,7 @@ { "category": "管理", "guid": "9945bda4-3334-4f24-a116-34182ba52752", + "id": "D03.13", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "中程度", "subcategory": "モニタリング", @@ -641,6 +704,7 @@ { "category": "管理", "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", + "id": "D03.14", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "severity": "中程度", "subcategory": "モニタリング", @@ -650,6 +714,7 @@ { "category": "管理", "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", + "id": "D03.15", "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "severity": "中程度", "subcategory": "モニタリング", @@ -659,6 +724,7 @@ { "category": "管理", "guid": "97be9951-9048-4384-9c98-6cb2913156a1", + "id": "D03.16", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "severity": "中程度", "subcategory": "モニタリング", @@ -668,6 +734,7 @@ { "category": "管理", "guid": "859c3900-4514-41eb-b010-475d695abd74", + "id": "D03.17", "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "severity": "中程度", "subcategory": "モニタリング", @@ -677,6 +744,7 @@ { "category": "管理", "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", + "id": "D03.18", "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "severity": "中程度", "subcategory": "モニタリング", @@ -686,6 +754,7 @@ { "category": "管理", "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", + "id": "D04.01", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "severity": "中程度", "subcategory": "運用上の互換性", @@ -696,6 +765,7 @@ "category": "管理", "description": "Azure Policy のゲスト構成機能では、マシン設定 (OS、アプリケーション、環境など) を監査および修復して、リソースが予想される構成に整合していることを確認でき、Update Management では VM のパッチ管理を適用できます。", "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", + "id": "D04.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "severity": "中程度", "subcategory": "運用上の互換性", @@ -705,6 +775,7 @@ { "category": "管理", "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", + "id": "D05.01", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "severity": "中程度", "subcategory": "保護と回復", @@ -714,6 +785,7 @@ { "category": "管理", "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", + "id": "D05.02", "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "severity": "中程度", "subcategory": "保護と回復", @@ -723,6 +795,7 @@ { "category": "管理", "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", + "id": "D05.03", "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "severity": "中程度", "subcategory": "保護と回復", @@ -732,6 +805,7 @@ { "category": "管理", "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", + "id": "E01.01", "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "severity": "高い", "subcategory": "フォールトトレランス", @@ -741,6 +815,7 @@ { "category": "管理", "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", + "id": "E01.02", "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "severity": "高い", "subcategory": "フォールトトレランス", @@ -750,6 +825,7 @@ { "category": "管理", "guid": "84101f59-1941-4195-a270-e28034290e3a", + "id": "E01.03", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "中程度", "subcategory": "フォールトトレランス", @@ -759,6 +835,7 @@ { "category": "管理", "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", + "id": "E02.01", "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "severity": "中程度", "subcategory": "拡張性", @@ -768,6 +845,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "F01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "中程度", "subcategory": "アプリ配信", @@ -777,6 +855,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "F01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "severity": "中程度", "subcategory": "アプリ配信", @@ -788,6 +867,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", "guid": "553585a6-abe0-11ed-afa1-0242ac120002", + "id": "F01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "中程度", "subcategory": "アプリ配信", @@ -799,6 +879,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "F01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "中程度", "subcategory": "アプリ配信", @@ -809,6 +890,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "F01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "中程度", "subcategory": "アプリ配信", @@ -820,6 +902,7 @@ "category": "ネットワーク トポロジと接続性", "description": "リバースプロキシ全般、特にWAFの管理は、ネットワークよりもアプリケーションに近いため、アプリと同じサブスクリプションに属します。アプリケーション ゲートウェイと WAF を接続サブスクリプションに一元化しても、1 つのチームで管理されている場合は問題ない可能性があります。", "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "F01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", "subcategory": "アプリ配信", @@ -830,6 +913,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "F01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", "subcategory": "アプリ配信", @@ -840,6 +924,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "F01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", "subcategory": "アプリ配信", @@ -850,6 +935,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "F01.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "中程度", "subcategory": "アプリ配信", @@ -860,6 +946,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "F01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "高い", "subcategory": "アプリ配信", @@ -870,6 +957,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "F01.11", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "低い", "subcategory": "アプリ配信", @@ -880,6 +968,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "F01.12", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "中程度", "subcategory": "アプリ配信", @@ -891,6 +980,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "F01.13", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "高い", "subcategory": "アプリ配信", @@ -900,6 +990,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "F01.14", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "高い", "subcategory": "アプリ配信", @@ -909,6 +1000,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "F01.15", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "高い", "subcategory": "アプリ配信", @@ -918,6 +1010,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "F01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "低い", "subcategory": "アプリ配信", @@ -927,6 +1020,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "F01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "中程度", "subcategory": "アプリ配信", @@ -936,6 +1030,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "F01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "低い", "subcategory": "アプリ配信", @@ -946,6 +1041,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "F01.19", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "高い", "subcategory": "アプリ配信", @@ -955,6 +1051,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "F01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "高い", "subcategory": "アプリ配信", @@ -964,6 +1061,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "F01.21", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "中程度", "subcategory": "アプリ配信", @@ -973,6 +1071,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "id": "F02.01", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "中程度", "subcategory": "暗号化", @@ -982,6 +1081,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "id": "F02.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "低い", "subcategory": "暗号化", @@ -992,6 +1092,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", + "id": "F03.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", "severity": "中程度", "subcategory": "ハブアンドスポーク", @@ -1002,6 +1103,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", + "id": "F03.02", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", "severity": "高い", "subcategory": "ハブアンドスポーク", @@ -1011,6 +1113,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", + "id": "F03.03", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", "severity": "中程度", "subcategory": "ハブアンドスポーク", @@ -1020,6 +1123,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", + "id": "F03.04", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", "severity": "低い", "subcategory": "ハブアンドスポーク", @@ -1030,6 +1134,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F03.05", "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", "severity": "低い", "subcategory": "ハブアンドスポーク", @@ -1039,6 +1144,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "id": "F03.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", "severity": "中程度", "subcategory": "ハブアンドスポーク", @@ -1049,6 +1155,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", + "id": "F03.07", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", "severity": "中程度", "subcategory": "ハブアンドスポーク", @@ -1060,6 +1167,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F03.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", "severity": "中程度", "subcategory": "ハブアンドスポーク", @@ -1070,6 +1178,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F03.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", "severity": "中程度", "subcategory": "ハブアンドスポーク", @@ -1080,6 +1189,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F03.10", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", "severity": "高い", "subcategory": "ハブアンドスポーク", @@ -1089,6 +1199,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", + "id": "F04.01", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1100,6 +1211,7 @@ "category": "ネットワーク トポロジと接続性", "description": "AS パスのプリペンドと接続の重みを使用して Azure からオンプレミスへのトラフィックに影響を与え、独自のルーターの BGP 属性の全範囲を使用してオンプレミスから Azure へのトラフィックに影響を与えることができます。", "guid": "f29812b2-363c-4efe-879b-599de0d5973c", + "id": "F04.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1111,6 +1223,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F04.03", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1122,6 +1235,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F04.04", "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", "severity": "高い", "subcategory": "ハイブリッド", @@ -1132,6 +1246,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F04.05", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", "severity": "高い", "subcategory": "ハイブリッド", @@ -1142,6 +1257,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F04.06", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1152,6 +1268,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", + "id": "F04.07", "link": "https://learn.microsoft.com/azure/networking/", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1162,6 +1279,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", + "id": "F04.08", "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1173,6 +1291,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F04.09", "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1183,6 +1302,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "id": "F04.10", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "高い", "subcategory": "ハイブリッド", @@ -1193,6 +1313,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "id": "F04.11", "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1203,6 +1324,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "b30e38c3-f298-412b-8363-cefe179b599d", + "id": "F04.12", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1213,6 +1335,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", + "id": "F04.13", "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1223,6 +1346,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", + "id": "F04.14", "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", "severity": "中程度", "subcategory": "ハイブリッド", @@ -1233,6 +1357,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "id": "F04.15", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", "severity": "高い", "subcategory": "ハイブリッド", @@ -1242,6 +1367,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "558fd772-49b8-4211-82df-27ee412e7f98", + "id": "F05.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "高い", "subcategory": "知財プラン", @@ -1253,6 +1379,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F05.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "低い", "subcategory": "知財プラン", @@ -1264,6 +1391,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F05.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "高い", "subcategory": "知財プラン", @@ -1274,6 +1402,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", + "id": "F05.04", "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", "severity": "高い", "subcategory": "知財プラン", @@ -1284,6 +1413,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", + "id": "F05.05", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "中程度", "subcategory": "知財プラン", @@ -1294,6 +1424,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", + "id": "F05.06", "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", "severity": "中程度", "subcategory": "知財プラン", @@ -1304,6 +1435,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", + "id": "F05.07", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "低い", "subcategory": "知財プラン", @@ -1313,6 +1445,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "614658d3-558f-4d77-849b-821112df27ee", + "id": "F05.08", "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", "severity": "高い", "subcategory": "知財プラン", @@ -1323,6 +1456,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "id": "F06.01", "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", "severity": "中程度", "subcategory": "インターネット", @@ -1333,7 +1467,8 @@ "category": "ネットワーク トポロジと接続性", "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", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet", "severity": "中程度", "subcategory": "インターネット", "text": "Azure 要塞はサブネット /26 以上で使用します。", @@ -1342,6 +1477,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", + "id": "F06.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "高い", "subcategory": "インターネット", @@ -1352,6 +1488,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", + "id": "F06.04", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "中程度", "subcategory": "インターネット", @@ -1362,6 +1499,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", + "id": "F06.05", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "低い", "subcategory": "インターネット", @@ -1372,6 +1510,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", + "id": "F06.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "severity": "中程度", "subcategory": "インターネット", @@ -1382,6 +1521,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", + "id": "F06.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "低い", "subcategory": "インターネット", @@ -1392,6 +1532,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", + "id": "F06.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "高い", "subcategory": "インターネット", @@ -1402,6 +1543,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", + "id": "F06.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", "severity": "高い", "subcategory": "インターネット", @@ -1413,6 +1555,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "id": "F06.10", "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", "severity": "高い", "subcategory": "インターネット", @@ -1423,6 +1566,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "id": "F06.11", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "高い", "subcategory": "インターネット", @@ -1433,6 +1577,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "id": "F06.12", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "高い", "subcategory": "インターネット", @@ -1443,6 +1588,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "id": "F06.13", "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", "severity": "高い", "subcategory": "インターネット", @@ -1453,6 +1599,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F06.14", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "severity": "高い", "subcategory": "インターネット", @@ -1462,6 +1609,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "F07.01", "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "severity": "高い", "subcategory": "PaaS", @@ -1472,6 +1620,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", + "id": "F07.02", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "中程度", "subcategory": "PaaS", @@ -1482,6 +1631,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", + "id": "F07.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "中程度", "subcategory": "PaaS", @@ -1493,6 +1643,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F07.04", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "中程度", "subcategory": "PaaS", @@ -1503,6 +1654,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", + "id": "F07.05", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "中程度", "subcategory": "PaaS", @@ -1514,6 +1666,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F08.01", "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", "severity": "高い", "subcategory": "セグメンテーション", @@ -1524,6 +1677,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F08.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", "severity": "高い", "subcategory": "セグメンテーション", @@ -1534,6 +1688,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F08.03", "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", "severity": "中程度", "subcategory": "セグメンテーション", @@ -1543,6 +1698,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", + "id": "F08.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", "severity": "中程度", "subcategory": "セグメンテーション", @@ -1553,6 +1709,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", + "id": "F08.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "中程度", "subcategory": "セグメンテーション", @@ -1564,6 +1721,7 @@ "category": "ネットワーク トポロジと接続性", "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": "F08.06", "severity": "中程度", "subcategory": "セグメンテーション", "text": "アプリケーション チームは、サブネット レベルの NSG でアプリケーション セキュリティ グループを使用して、ランディング ゾーン内の多層 VM を保護する必要があります。", @@ -1573,6 +1731,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", + "id": "F08.07", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "中程度", "subcategory": "セグメンテーション", @@ -1583,6 +1742,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "dfe237de-143b-416c-91d7-aa9b64704489", + "id": "F08.08", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "中程度", "subcategory": "セグメンテーション", @@ -1593,6 +1753,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", + "id": "F09.01", "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1603,6 +1764,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", + "id": "F09.02", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1612,6 +1774,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", + "id": "F09.03", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "低い", "subcategory": "仮想 WAN", @@ -1622,6 +1785,7 @@ "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", + "id": "F09.04", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1632,6 +1796,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "id": "F09.05", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1641,6 +1806,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "id": "F09.06", "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1650,6 +1816,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "id": "F09.07", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1659,6 +1826,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "id": "F09.08", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1668,6 +1836,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "id": "F09.09", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", "severity": "中程度", "subcategory": "仮想 WAN", @@ -1677,6 +1846,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "9c75dfef-573c-461c-a698-68598595581a", + "id": "F09.10", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", "severity": "高い", "subcategory": "仮想 WAN", @@ -1686,6 +1856,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "G01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "高い", "subcategory": "アプリ配信", @@ -1695,6 +1866,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "G01.02", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "中程度", "subcategory": "アプリ配信", @@ -1704,6 +1876,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "G01.03", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "高い", "subcategory": "アプリ配信", @@ -1713,6 +1886,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "G01.04", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "高い", "subcategory": "アプリ配信", @@ -1722,6 +1896,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "G01.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "高い", "subcategory": "アプリ配信", @@ -1731,6 +1906,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "G01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "高い", "subcategory": "アプリ配信", @@ -1740,6 +1916,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "G01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "高い", "subcategory": "アプリ配信", @@ -1749,6 +1926,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "G01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "中程度", "subcategory": "アプリ配信", @@ -1758,6 +1936,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "G01.09", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "中程度", "subcategory": "アプリ配信", @@ -1767,6 +1946,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "G01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "中程度", "subcategory": "アプリ配信", @@ -1776,6 +1956,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "G01.11", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "低い", "subcategory": "アプリ配信", @@ -1785,6 +1966,7 @@ { "category": "ネットワーク トポロジと接続性", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "G01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "中程度", "subcategory": "アプリ配信", @@ -1794,7 +1976,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", "severity": "高い", "subcategory": "DevOps チームのトポロジ", "text": "Azure ランディング ゾーン アーキテクチャを構築、管理、保守するためのクロスファンクショナルな DevOps プラットフォーム チームがあることを確認します。", @@ -1803,7 +1986,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "低い", "subcategory": "DevOps チームのトポロジ", "text": "Azure ランディング ゾーン プラットフォーム チームの関数を定義することを目指します。", @@ -1812,7 +1996,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "低い", "subcategory": "DevOps チームのトポロジ", "text": "アプリケーション ワークロード チームが自給自足し、DevOps プラットフォーム チームのサポートを必要としない機能を定義することを目指します。これは、カスタム RBAC ロールを使用して実現します。", @@ -1821,7 +2006,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "165eb5e9-b434-448a-9e24-178632186212", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H01.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "高い", "subcategory": "DevOps チームのトポロジ", "text": "CI/CD パイプラインを使用して IaC アーティファクトをデプロイし、デプロイと Azure 環境の品質を確保します。", @@ -1830,7 +2016,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "中程度", "subcategory": "DevOps チームのトポロジ", "text": "ビルド プロセスの一部として IaC とアプリケーション コードの単体テストを含めます。", @@ -1839,7 +2026,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "高い", "subcategory": "DevOps チームのトポロジ", "text": "Key Vault シークレットを使用して、資格情報 (仮想マシンのユーザー パスワード)、証明書、キーなどの機密情報がハードコーディングされないようにします。", @@ -1848,7 +2036,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", "severity": "低い", "subcategory": "DevOps チームのトポロジ", "text": "アプリケーションとワークロードのファイル>新しい>ランディング ゾーンの自動化を実装します。", @@ -1857,7 +2046,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "高い", "subcategory": "開発ライフサイクル", "text": "アプリケーションと開発された IaC のソース コードにバージョン管理システムが使用されていることを確認します。マイクロソフトは Git を推奨しています。", @@ -1866,7 +2056,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "低い", "subcategory": "開発ライフサイクル", "text": "分岐戦略に従って、チームがより適切にコラボレーションし、IaC とアプリケーション コードのバージョン管理を効率的に管理できるようにします。Github Flow などのオプションを確認します。", @@ -1875,7 +2066,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "中程度", "subcategory": "開発ライフサイクル", "text": "プル要求戦略を採用して、ブランチにマージされたコード変更の制御を維持します。", @@ -1884,7 +2076,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "高い", "subcategory": "開発戦略", "text": "Azure Bicep、ARM テンプレート、Terraform などの宣言型インフラストラクチャをコードとして活用して、Azure ランディング ゾーン アーキテクチャを構築および保守します。プラットフォームとアプリケーションの両方のワークロードの観点から。", @@ -1893,7 +2086,8 @@ { "category": "プラットフォームの自動化と DevOps", "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", + "id": "H04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", "severity": "高い", "subcategory": "安全", "text": "DevOps の開発と運用のすでに組み合わされたプロセスにセキュリティを統合して、イノベーション プロセスのリスクを軽減します。", @@ -1902,6 +2096,7 @@ { "category": "リソース構成", "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", + "id": "I01.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", "severity": "高い", "subcategory": "名前付けとタグ付け", @@ -1912,6 +2107,7 @@ "category": "リソース構成", "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": "I02.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1923,6 +2119,7 @@ "category": "リソース構成", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", + "id": "I02.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1933,6 +2130,7 @@ { "category": "リソース構成", "guid": "667313b4-f566-44b5-b984-a859c773e7d2", + "id": "I02.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1943,6 +2141,7 @@ { "category": "リソース構成", "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", + "id": "I02.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1953,6 +2152,7 @@ { "category": "リソース構成", "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", + "id": "I02.05", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1964,6 +2164,7 @@ "category": "リソース構成", "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": "I02.06", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1973,6 +2174,7 @@ { "category": "リソース構成", "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", + "id": "I02.07", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1982,6 +2184,7 @@ { "category": "リソース構成", "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", + "id": "I02.08", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "中程度", "subcategory": "サブスクリプション", @@ -1991,6 +2194,7 @@ { "category": "リソース構成", "guid": "49b82111-2df2-47ee-912e-7f983f630472", + "id": "I02.09", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "高い", "subcategory": "サブスクリプション", @@ -2000,6 +2204,7 @@ { "category": "リソース構成", "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", + "id": "I02.10", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "中程度", "subcategory": "サブスクリプション", @@ -2009,6 +2214,7 @@ { "category": "リソース構成", "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", + "id": "I02.11", "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", "severity": "高い", "subcategory": "サブスクリプション", @@ -2019,6 +2225,7 @@ { "category": "リソース構成", "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", + "id": "I02.12", "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", "severity": "高い", "subcategory": "サブスクリプション", @@ -2029,6 +2236,7 @@ { "category": "リソース構成", "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "I02.13", "link": "https://azure.microsoft.com/global-infrastructure/services/", "severity": "中程度", "subcategory": "サブスクリプション", @@ -2039,6 +2247,7 @@ { "category": "リソース構成", "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "I02.14", "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", "severity": "高い", "subcategory": "サブスクリプション", @@ -2049,6 +2258,7 @@ { "category": "リソース構成", "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "I02.15", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "中程度", "subcategory": "サブスクリプション", @@ -2060,6 +2270,7 @@ "category": "リソース構成", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", + "id": "I02.16", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", "severity": "中程度", "subcategory": "サブスクリプション", @@ -2070,6 +2281,7 @@ { "category": "安全", "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", + "id": "J01.01", "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "severity": "中程度", "subcategory": "アクセス制御", @@ -2079,6 +2291,7 @@ { "category": "安全", "guid": "01365d38-e43f-49cc-ad86-8266abca264f", + "id": "J01.02", "link": "https://www.microsoft.com/security/business/zero-trust", "severity": "中程度", "subcategory": "アクセス制御", @@ -2088,6 +2301,7 @@ { "category": "安全", "guid": "5017f154-e3ab-4369-9829-e7e316183687", + "id": "J02.01", "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "severity": "高い", "subcategory": "暗号化とキー", @@ -2098,6 +2312,7 @@ "category": "安全", "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": "J02.02", "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2107,6 +2322,7 @@ { "category": "安全", "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", + "id": "J02.03", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2116,6 +2332,7 @@ { "category": "安全", "guid": "dc055bcf-619e-48a1-9f98-879525d62688", + "id": "J02.04", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2125,6 +2342,7 @@ { "category": "安全", "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "J02.05", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2134,6 +2352,7 @@ { "category": "安全", "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "J02.06", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2143,6 +2362,7 @@ { "category": "安全", "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", + "id": "J02.07", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2152,6 +2372,7 @@ { "category": "安全", "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", + "id": "J02.08", "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2161,6 +2382,7 @@ { "category": "安全", "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", + "id": "J02.09", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2170,6 +2392,7 @@ { "category": "安全", "guid": "16183687-a047-47a2-8994-5bda43334f24", + "id": "J02.10", "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2179,6 +2402,7 @@ { "category": "安全", "guid": "91163418-2ba5-4275-8694-4008be7d7e48", + "id": "J02.11", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2188,6 +2412,7 @@ { "category": "安全", "guid": "25d62688-6d70-4ba6-a97b-e99519048384", + "id": "J02.12", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "中程度", "subcategory": "暗号化とキー", @@ -2197,6 +2422,7 @@ { "category": "安全", "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", + "id": "J03.01", "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "severity": "中程度", "subcategory": "オペレーションズ", @@ -2206,6 +2432,7 @@ { "category": "安全", "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", + "id": "J03.02", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "severity": "中程度", "subcategory": "オペレーションズ", @@ -2215,15 +2442,47 @@ { "category": "安全", "guid": "09945bda-4333-44f2-9911-634182ba5275", - "link": "https://learn.microsoft.com/azure/security-center/", - "severity": "中程度", + "id": "J03.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", + "severity": "高い", + "subcategory": "オペレーションズ", + "text": "すべてのサブスクリプションに対して Defender クラウド セキュリティ体制管理を有効にします。", + "waf": "安全" + }, + { + "category": "安全", + "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", + "id": "J03.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", + "severity": "高い", + "subcategory": "オペレーションズ", + "text": "すべてのサブスクリプションでサーバーの Defender クラウド ワークロード保護プランを有効にします。", + "waf": "安全" + }, + { + "category": "安全", + "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", + "id": "J03.05", + "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", + "severity": "高い", + "subcategory": "オペレーションズ", + "text": "すべてのサブスクリプションで Azure リソースの Defender クラウド ワークロード保護プランを有効にします。", + "waf": "安全" + }, + { + "category": "安全", + "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", + "id": "J03.06", + "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection", + "severity": "高い", "subcategory": "オペレーションズ", - "text": "すべてのサブスクリプションに対してクラウド標準の Defender を有効にします。", + "text": "IaaS サーバーでエンドポイント保護を有効にします。", "waf": "安全" }, { "category": "安全", "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "J03.07", "link": "https://learn.microsoft.com/azure/security-center/", "severity": "中程度", "subcategory": "オペレーションズ", @@ -2233,6 +2492,7 @@ { "category": "安全", "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", + "id": "J03.08", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "中程度", "subcategory": "オペレーションズ", @@ -2242,6 +2502,7 @@ { "category": "安全", "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", + "id": "J04.01", "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", "severity": "高い", "subcategory": "概要", @@ -2251,6 +2512,7 @@ { "category": "安全", "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", + "id": "J04.02", "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", "severity": "高い", "subcategory": "概要", @@ -2260,16 +2522,17 @@ { "category": "安全", "guid": "6f704104-85c1-441f-96d3-c9819911645e", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/roles/security-planning", + "id": "J05.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning", "severity": "高い", "subcategory": "安全な特権アクセス", "text": "Azure 管理タスク用に特権を持つ管理者アカウントを分離します。", - "training": "", "waf": "安全" }, { "category": "安全", "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", + "id": "J06.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "中程度", "subcategory": "サービスイネーブルメントフレームワーク", @@ -2279,6 +2542,7 @@ { "category": "安全", "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", + "id": "J06.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "中程度", "subcategory": "サービスイネーブルメントフレームワーク", @@ -2289,7 +2553,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "September 07, 2023" + "timestamp": "September 14, 2023" }, "severities": [ { diff --git a/checklists/alz_checklist.ko.json b/checklists/alz_checklist.ko.json index 97a02fc93..2bf772aff 100644 --- a/checklists/alz_checklist.ko.json +++ b/checklists/alz_checklist.ko.json @@ -29,17 +29,19 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", - "link": "https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/considerations/tenancy-models", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations", "severity": "보통", "subcategory": "Azure AD 테넌트", - "text": "얼마나 많은 Azure AD 테넌트를 관리하나요?", + "text": "다중 테넌트에 대한 명확한 규정 또는 비즈니스 요구 사항이 없는 한 Azure 리소스를 관리하기 위해 하나의 Entra 테넌트를 사용합니다.", "waf": "작업" }, { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", - "severity": "보통", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", + "severity": "낮다", "subcategory": "Azure AD 테넌트", "text": "Azure AD 테넌트를 관리하기 위한 다중 테넌트 자동화 접근 방식이 있는지 확인합니다.", "waf": "작업" @@ -47,8 +49,9 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", - "severity": "보통", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "severity": "낮다", "subcategory": "Azure AD 테넌트", "text": "다중 테넌트 관리를 위해 Azure Lighthouse 활용", "waf": "작업" @@ -56,7 +59,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "보통", "subcategory": "클라우드 솔루션 공급자", "text": "Azure Lighthouse가 파트너별로 테넌트를 관리하는 데 사용되는지 확인합니다.", @@ -65,7 +69,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "낮다", "subcategory": "클라우드 솔루션 공급자", "text": "CSP 파트너와 지원 요청 및 에스컬레이션 프로세스에 대해 논의", @@ -74,7 +79,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "32952499-58c8-4e6f-ada5-972e67893d55", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "보통", "subcategory": "클라우드 솔루션 공급자", "text": "Azure Cost Management를 사용하여 비용 보고 및 보기 설정Setup Cost Reporting and Views with Azure Cost Management", @@ -83,7 +89,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "severity": "보통", "subcategory": "기업계약", "text": "그룹 사서함에 대한 알림 연락처 구성", @@ -92,7 +99,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "낮다", "subcategory": "기업계약", "text": "부서 및 계정을 사용하여 조직의 구조를 등록 계층 구조에 매핑하면 청구를 분리하는 데 도움이 될 수 있습니다.", @@ -101,7 +109,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "높다", "subcategory": "기업계약", "text": "계정이 '회사 및 학교 계정' 형식으로 구성되어 있는지 확인합니다.", @@ -110,7 +119,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "보통", "subcategory": "기업계약", "text": "EA 등록에서 DA 요금 보기 및 AO 요금 보기를 모두 사용하도록 설정하여 사용자가 비용 및 청구 데이터를 올바르게 검토할 수 있도록 합니다.", @@ -119,7 +129,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "낮다", "subcategory": "기업계약", "text": "Enterprise 개발/테스트 구독을 사용하여 비프로덕션 워크로드에 대한 비용 절감Make use of Enterprise Dev/Test Subscriptions to reduce costs for non-production workloads", @@ -128,7 +139,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "보통", "subcategory": "기업계약", "text": "역할 할당을 정기적으로 감사하여 기업계약 등록에 액세스할 수 있는 사용자를 검토합니다.", @@ -137,7 +149,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "낮다", "subcategory": "Microsoft 클라우드 계약", "text": "계약 청구 계정 알림 연락처 전자 메일 구성", @@ -146,7 +159,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/mca-section-invoice", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "severity": "낮다", "subcategory": "Microsoft 클라우드 계약", "text": "청구 프로필 및 청구서 섹션을 사용하여 효과적인 비용 관리를 위해 계약 청구를 구성합니다", @@ -155,7 +169,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "낮다", "subcategory": "Microsoft 클라우드 계약", "text": "Azure Plan을 사용하여 비프로덕션 워크로드에 대한 비용 절감", @@ -164,7 +179,8 @@ { "category": "Azure 청구 및 Active Directory 테넌트", "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "보통", "subcategory": "Microsoft 클라우드 계약", "text": "계약 청구 RBAC 역할 할당을 주기적으로 감사하여 MCA 청구 계정에 액세스할 수 있는 사용자를 검토합니다", @@ -173,6 +189,7 @@ { "category": "거버넌스", "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", + "id": "B01.01", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "높다", "subcategory": "거버넌스", @@ -182,6 +199,7 @@ { "category": "거버넌스", "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", + "id": "B01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", "severity": "보통", "subcategory": "거버넌스", @@ -191,6 +209,7 @@ { "category": "거버넌스", "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", + "id": "B01.03", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "보통", "subcategory": "거버넌스", @@ -200,6 +219,7 @@ { "category": "거버넌스", "guid": "223ace8c-b123-408c-a501-7f154e3ab369", + "id": "B01.04", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "보통", "subcategory": "거버넌스", @@ -209,6 +229,7 @@ { "category": "거버넌스", "guid": "3829e7e3-1618-4368-9a04-77a209945bda", + "id": "B01.05", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "보통", "subcategory": "거버넌스", @@ -218,6 +239,7 @@ { "category": "거버넌스", "guid": "43334f24-9116-4341-a2ba-527526944008", + "id": "B01.06", "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "severity": "낮다", "subcategory": "거버넌스", @@ -227,6 +249,7 @@ { "category": "거버넌스", "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", + "id": "B01.07", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "보통", "subcategory": "거버넌스", @@ -237,6 +260,7 @@ "category": "거버넌스", "description": "리소스 정책 참가자 역할을 특정 범위에 할당하면 관련 팀에 정책 관리를 위임할 수 있습니다. 예를 들어 중앙 IT 팀은 관리 그룹 수준 정책을 감독하고 애플리케이션 팀은 구독에 대한 정책을 처리하여 조직 표준을 준수하여 분산 거버넌스를 가능하게 할 수 있습니다.", "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", + "id": "B01.08", "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "severity": "보통", "subcategory": "거버넌스", @@ -246,6 +270,7 @@ { "category": "거버넌스", "guid": "19048384-5c98-46cb-8913-156a12476e49", + "id": "B01.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "보통", "subcategory": "거버넌스", @@ -255,7 +280,8 @@ { "category": "거버넌스", "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", - "link": "https://learn.microsoft.com/en-us/azure/automation/automation-solution-vm-management-config", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "severity": "낮다", "subcategory": "클라우드 투자 최적화", "text": "자동화 태그를 사용하여 사용자 환경에서 VM을 시작/중지하여 비용을 절감하는 것이 좋습니다.", @@ -264,7 +290,8 @@ { "category": "거버넌스", "guid": "29fd366b-a180-452b-9bd7-954b7700c667", - "link": "https://learn.microsoft.com/en-us/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", + "id": "B02.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", "severity": "보통", "subcategory": "클라우드 투자 최적화", "text": "'실제' 및 '예측' 예산 경고를 구성합니다.", @@ -273,16 +300,18 @@ { "category": "ID 및 액세스 관리", "guid": "4348bf81-7573-4512-8f46-9061cc198fea", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", + "id": "C01.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", "severity": "높다", "subcategory": "Active Directory 및 하이브리드 ID", "text": "Azure 서비스에 대한 인증에 서비스 주체 대신 관리 ID 사용Use managed identities instead of service principals for authentication to Azure services", - "training": "https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", "waf": "안전" }, { "category": "ID 및 액세스 관리", "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", + "id": "C02.01", "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "severity": "보통", "subcategory": "Azure AD", @@ -292,6 +321,7 @@ { "category": "ID 및 액세스 관리", "guid": "984a859c-773e-47d2-9162-3a765a917e1f", + "id": "C03.01", "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "severity": "높다", "subcategory": "신원", @@ -302,16 +332,17 @@ { "category": "ID 및 액세스 관리", "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "severity": "보통", "subcategory": "신원", "text": "Azure AD 로그를 플랫폼 중앙 Azure Monitor와 통합합니다. Azure Monitor를 사용하면 Azure의 로그 및 모니터링 데이터에 대한 단일 정보 원본을 사용할 수 있으므로 조직에 로그 수집 및 보존에 대한 요구 사항을 충족하는 클라우드 네이티브 옵션을 제공합니다.", - "training": "", "waf": "안전" }, { "category": "ID 및 액세스 관리", "guid": "348ef254-c27d-442e-abba-c7571559ab91", + "id": "C03.03", "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "severity": "높다", "subcategory": "신원", @@ -322,6 +353,7 @@ { "category": "ID 및 액세스 관리", "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", + "id": "C03.04", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "severity": "낮다", "subcategory": "신원", @@ -332,6 +364,7 @@ { "category": "ID 및 액세스 관리", "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", + "id": "C03.05", "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "severity": "높다", "subcategory": "신원", @@ -342,6 +375,7 @@ { "category": "ID 및 액세스 관리", "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", + "id": "C03.06", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "severity": "보통", "subcategory": "신원", @@ -352,6 +386,7 @@ { "category": "ID 및 액세스 관리", "guid": "14658d35-58fd-4772-99b8-21112df27ee4", + "id": "C03.07", "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "severity": "보통", "subcategory": "신원", @@ -362,6 +397,7 @@ { "category": "ID 및 액세스 관리", "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", + "id": "C03.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", "severity": "높다", "subcategory": "신원", @@ -372,6 +408,7 @@ { "category": "ID 및 액세스 관리", "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", + "id": "C03.09", "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "severity": "보통", "subcategory": "신원", @@ -382,6 +419,7 @@ { "category": "ID 및 액세스 관리", "guid": "f5664b5e-984a-4859-a773-e7d261623a76", + "id": "C03.10", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "severity": "보통", "subcategory": "신원", @@ -392,6 +430,7 @@ { "category": "ID 및 액세스 관리", "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", + "id": "C03.11", "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "severity": "보통", "subcategory": "신원", @@ -402,6 +441,7 @@ { "category": "ID 및 액세스 관리", "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", + "id": "C03.12", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "보통", "subcategory": "신원", @@ -412,6 +452,7 @@ { "category": "ID 및 액세스 관리", "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", + "id": "C03.13", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "보통", "subcategory": "신원", @@ -422,6 +463,7 @@ { "category": "ID 및 액세스 관리", "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", + "id": "C03.14", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "severity": "보통", "subcategory": "신원", @@ -432,6 +474,7 @@ { "category": "ID 및 액세스 관리", "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", + "id": "C03.15", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "severity": "보통", "subcategory": "신원", @@ -442,6 +485,7 @@ { "category": "ID 및 액세스 관리", "guid": "35037e68-9349-4c15-b371-228514f4cdff", + "id": "C03.16", "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", "severity": "보통", "subcategory": "신원", @@ -452,36 +496,39 @@ { "category": "ID 및 액세스 관리", "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "id": "C04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "severity": "낮다", "subcategory": "착륙 구역", "text": "가상 네트워크를 사용하여 ID(ADDS) 네트워크 구분을 구성하고 허브에 다시 피어링합니다. 응용 프로그램 랜딩 존(레거시) 내에서 인증을 제공합니다.", - "training": "https://learn.microsoft.com/en-us/azure/architecture/example-scenario/identity/adds-extend-domain", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", "waf": "안전" }, { "category": "ID 및 액세스 관리", "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "id": "C04.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "severity": "보통", "subcategory": "착륙 구역", "text": "가능한 경우 Azure RBAC를 사용하여 리소스에 대한 데이터 평면 액세스를 관리합니다. 예: Keyvault, 스토리지 계정 및 데이터베이스 서비스 전반의 데이터 작업. ", - "training": "https://learn.microsoft.com/en-us/azure/role-based-access-control/overview", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", "waf": "안전" }, { "category": "ID 및 액세스 관리", "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "id": "C04.03", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "severity": "보통", "subcategory": "착륙 구역", "text": "Azure AD PIM 액세스 검토를 사용하여 리소스 자격의 유효성을 주기적으로 검사합니다.", - "training": "", "waf": "안전" }, { "category": "경영", "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", + "id": "D01.01", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "severity": "높다", "subcategory": "앱 제공", @@ -491,6 +538,7 @@ { "category": "경영", "guid": "7f408960-c626-44cb-a018-347c8d790cdf", + "id": "D01.02", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "severity": "보통", "subcategory": "앱 제공", @@ -500,6 +548,7 @@ { "category": "경영", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", + "id": "D02.01", "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "severity": "보통", "subcategory": "데이터 보호", @@ -509,6 +558,7 @@ { "category": "경영", "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", + "id": "D02.02", "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "severity": "보통", "subcategory": "데이터 보호", @@ -518,6 +568,7 @@ { "category": "경영", "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", + "id": "D03.01", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "보통", "subcategory": "모니터링", @@ -528,6 +579,7 @@ { "category": "경영", "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "D03.02", "severity": "보통", "subcategory": "모니터링", "text": "랜딩 존이 문서화되어 있습니까?", @@ -536,7 +588,8 @@ { "category": "경영", "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", - "link": "https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "severity": "보통", "subcategory": "모니터링", "text": "로그 보존 요구 사항이 2년을 초과하는 경우 Azure Monitor 로그를 사용합니다. 현재 최대 7년 동안 데이터를 보관된 상태로 유지할 수 있습니다.", @@ -546,6 +599,7 @@ { "category": "경영", "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", + "id": "D03.04", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "보통", "subcategory": "모니터링", @@ -556,6 +610,7 @@ { "category": "경영", "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", + "id": "D03.05", "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "severity": "보통", "subcategory": "모니터링", @@ -566,6 +621,7 @@ { "category": "경영", "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", + "id": "D03.06", "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "severity": "보통", "subcategory": "모니터링", @@ -576,6 +632,7 @@ { "category": "경영", "guid": "90483845-c986-4cb2-a131-56a12476e49f", + "id": "D03.07", "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "severity": "보통", "subcategory": "모니터링", @@ -586,6 +643,7 @@ { "category": "경영", "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", + "id": "D03.08", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "severity": "보통", "subcategory": "모니터링", @@ -596,6 +654,7 @@ { "category": "경영", "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", + "id": "D03.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "낮다", "subcategory": "모니터링", @@ -605,6 +664,7 @@ { "category": "경영", "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", + "id": "D03.10", "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", "severity": "보통", "subcategory": "모니터링", @@ -614,6 +674,7 @@ { "category": "경영", "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", + "id": "D03.11", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "severity": "보통", "subcategory": "모니터링", @@ -623,6 +684,7 @@ { "category": "경영", "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", + "id": "D03.12", "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "severity": "보통", "subcategory": "모니터링", @@ -632,6 +694,7 @@ { "category": "경영", "guid": "9945bda4-3334-4f24-a116-34182ba52752", + "id": "D03.13", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "보통", "subcategory": "모니터링", @@ -641,6 +704,7 @@ { "category": "경영", "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", + "id": "D03.14", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "severity": "보통", "subcategory": "모니터링", @@ -650,6 +714,7 @@ { "category": "경영", "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", + "id": "D03.15", "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "severity": "보통", "subcategory": "모니터링", @@ -659,6 +724,7 @@ { "category": "경영", "guid": "97be9951-9048-4384-9c98-6cb2913156a1", + "id": "D03.16", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "severity": "보통", "subcategory": "모니터링", @@ -668,6 +734,7 @@ { "category": "경영", "guid": "859c3900-4514-41eb-b010-475d695abd74", + "id": "D03.17", "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "severity": "보통", "subcategory": "모니터링", @@ -677,6 +744,7 @@ { "category": "경영", "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", + "id": "D03.18", "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "severity": "보통", "subcategory": "모니터링", @@ -686,6 +754,7 @@ { "category": "경영", "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", + "id": "D04.01", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "severity": "보통", "subcategory": "운영 적합성", @@ -696,6 +765,7 @@ "category": "경영", "description": "Azure Policy의 게스트 구성 기능은 컴퓨터 설정(예: OS, 애플리케이션, 환경)을 감사하고 수정하여 리소스가 예상 구성과 일치하도록 할 수 있으며, 업데이트 관리는 VM에 대한 패치 관리를 적용할 수 있습니다.", "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", + "id": "D04.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "severity": "보통", "subcategory": "운영 적합성", @@ -705,6 +775,7 @@ { "category": "경영", "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", + "id": "D05.01", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "severity": "보통", "subcategory": "보호 및 복구", @@ -714,6 +785,7 @@ { "category": "경영", "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", + "id": "D05.02", "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "severity": "보통", "subcategory": "보호 및 복구", @@ -723,6 +795,7 @@ { "category": "경영", "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", + "id": "D05.03", "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "severity": "보통", "subcategory": "보호 및 복구", @@ -732,6 +805,7 @@ { "category": "경영 ", "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", + "id": "E01.01", "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "severity": "높다", "subcategory": "내결함성", @@ -741,6 +815,7 @@ { "category": "경영 ", "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", + "id": "E01.02", "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "severity": "높다", "subcategory": "내결함성", @@ -750,6 +825,7 @@ { "category": "경영 ", "guid": "84101f59-1941-4195-a270-e28034290e3a", + "id": "E01.03", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "보통", "subcategory": "내결함성", @@ -759,6 +835,7 @@ { "category": "경영 ", "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", + "id": "E02.01", "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "severity": "보통", "subcategory": "확장성", @@ -768,6 +845,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "F01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "보통", "subcategory": "앱 제공", @@ -777,6 +855,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "F01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "severity": "보통", "subcategory": "앱 제공", @@ -788,6 +867,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant", "guid": "553585a6-abe0-11ed-afa1-0242ac120002", + "id": "F01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "보통", "subcategory": "앱 제공", @@ -799,6 +879,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "F01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "보통", "subcategory": "앱 제공", @@ -809,6 +890,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "F01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "보통", "subcategory": "앱 제공", @@ -820,6 +902,7 @@ "category": "네트워크 토폴로지 및 연결", "description": "일반적으로 역방향 프록시 및 특히 WAF의 관리는 네트워킹보다 애플리케이션에 더 가깝기 때문에 앱과 동일한 구독에 속합니다. 연결 구독에서 Application Gateway 및 WAF를 중앙 집중화하는 것은 단일 팀에서 관리하는 경우 괜찮을 수 있습니다.", "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "F01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", "subcategory": "앱 제공", @@ -830,6 +913,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "F01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", "subcategory": "앱 제공", @@ -840,6 +924,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "F01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", "subcategory": "앱 제공", @@ -850,6 +935,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "F01.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "보통", "subcategory": "앱 제공", @@ -860,6 +946,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "F01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "높다", "subcategory": "앱 제공", @@ -870,6 +957,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "F01.11", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "낮다", "subcategory": "앱 제공", @@ -880,6 +968,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "F01.12", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "보통", "subcategory": "앱 제공", @@ -891,6 +980,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "F01.13", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "높다", "subcategory": "앱 제공", @@ -900,6 +990,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "F01.14", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "높다", "subcategory": "앱 제공", @@ -909,6 +1000,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "F01.15", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "높다", "subcategory": "앱 제공", @@ -918,6 +1010,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "F01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "낮다", "subcategory": "앱 제공", @@ -927,6 +1020,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "F01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "보통", "subcategory": "앱 제공", @@ -936,6 +1030,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "F01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "낮다", "subcategory": "앱 제공", @@ -946,6 +1041,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "F01.19", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "높다", "subcategory": "앱 제공", @@ -955,6 +1051,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "F01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "높다", "subcategory": "앱 제공", @@ -964,6 +1061,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "F01.21", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "보통", "subcategory": "앱 제공", @@ -973,6 +1071,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "id": "F02.01", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "보통", "subcategory": "암호화", @@ -982,6 +1081,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "id": "F02.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "낮다", "subcategory": "암호화", @@ -992,6 +1092,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", + "id": "F03.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", "severity": "보통", "subcategory": "허브 및 스포크", @@ -1002,6 +1103,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", + "id": "F03.02", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", "severity": "높다", "subcategory": "허브 및 스포크", @@ -1011,6 +1113,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", + "id": "F03.03", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", "severity": "보통", "subcategory": "허브 및 스포크", @@ -1020,6 +1123,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", + "id": "F03.04", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", "severity": "낮다", "subcategory": "허브 및 스포크", @@ -1030,6 +1134,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F03.05", "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", "severity": "낮다", "subcategory": "허브 및 스포크", @@ -1039,6 +1144,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "id": "F03.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", "severity": "보통", "subcategory": "허브 및 스포크", @@ -1049,6 +1155,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", + "id": "F03.07", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", "severity": "보통", "subcategory": "허브 및 스포크", @@ -1060,6 +1167,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F03.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", "severity": "보통", "subcategory": "허브 및 스포크", @@ -1070,6 +1178,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F03.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", "severity": "보통", "subcategory": "허브 및 스포크", @@ -1080,6 +1189,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F03.10", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", "severity": "높다", "subcategory": "허브 및 스포크", @@ -1089,6 +1199,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", + "id": "F04.01", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", "severity": "보통", "subcategory": "잡종", @@ -1100,6 +1211,7 @@ "category": "네트워크 토폴로지 및 연결", "description": "AS-path 접두사 및 연결 가중치를 사용하여 Azure에서 온-프레미스로의 트래픽에 영향을 주고, 자체 라우터의 전체 BGP 특성을 사용하여 온-프레미스에서 Azure로의 트래픽에 영향을 줄 수 있습니다.", "guid": "f29812b2-363c-4efe-879b-599de0d5973c", + "id": "F04.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "보통", "subcategory": "잡종", @@ -1111,6 +1223,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F04.03", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "보통", "subcategory": "잡종", @@ -1122,6 +1235,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F04.04", "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", "severity": "높다", "subcategory": "잡종", @@ -1132,6 +1246,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F04.05", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", "severity": "높다", "subcategory": "잡종", @@ -1142,6 +1257,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F04.06", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", "severity": "보통", "subcategory": "잡종", @@ -1152,6 +1268,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", + "id": "F04.07", "link": "https://learn.microsoft.com/azure/networking/", "severity": "보통", "subcategory": "잡종", @@ -1162,6 +1279,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", + "id": "F04.08", "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", "severity": "보통", "subcategory": "잡종", @@ -1173,6 +1291,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F04.09", "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", "severity": "보통", "subcategory": "잡종", @@ -1183,6 +1302,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "id": "F04.10", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "높다", "subcategory": "잡종", @@ -1193,6 +1313,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "id": "F04.11", "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", "severity": "보통", "subcategory": "잡종", @@ -1203,6 +1324,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "b30e38c3-f298-412b-8363-cefe179b599d", + "id": "F04.12", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", "severity": "보통", "subcategory": "잡종", @@ -1213,6 +1335,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", + "id": "F04.13", "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", "severity": "보통", "subcategory": "잡종", @@ -1223,6 +1346,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", + "id": "F04.14", "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", "severity": "보통", "subcategory": "잡종", @@ -1233,6 +1357,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "id": "F04.15", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", "severity": "높다", "subcategory": "잡종", @@ -1242,6 +1367,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "558fd772-49b8-4211-82df-27ee412e7f98", + "id": "F05.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "높다", "subcategory": "IP 플랜", @@ -1253,6 +1379,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F05.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "낮다", "subcategory": "IP 플랜", @@ -1264,6 +1391,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F05.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "높다", "subcategory": "IP 플랜", @@ -1274,6 +1402,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", + "id": "F05.04", "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", "severity": "높다", "subcategory": "IP 플랜", @@ -1284,6 +1413,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", + "id": "F05.05", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "보통", "subcategory": "IP 플랜", @@ -1294,6 +1424,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", + "id": "F05.06", "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", "severity": "보통", "subcategory": "IP 플랜", @@ -1304,6 +1435,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", + "id": "F05.07", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "낮다", "subcategory": "IP 플랜", @@ -1313,6 +1445,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "614658d3-558f-4d77-849b-821112df27ee", + "id": "F05.08", "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", "severity": "높다", "subcategory": "IP 플랜", @@ -1323,6 +1456,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "id": "F06.01", "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", "severity": "보통", "subcategory": "인터넷", @@ -1333,7 +1467,8 @@ "category": "네트워크 토폴로지 및 연결", "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", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet", "severity": "보통", "subcategory": "인터넷", "text": "서브넷 /26 이상에서 Azure Bastion을 사용합니다.", @@ -1342,6 +1477,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", + "id": "F06.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "높다", "subcategory": "인터넷", @@ -1352,6 +1488,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", + "id": "F06.04", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "보통", "subcategory": "인터넷", @@ -1362,6 +1499,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", + "id": "F06.05", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "낮다", "subcategory": "인터넷", @@ -1372,6 +1510,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", + "id": "F06.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "severity": "보통", "subcategory": "인터넷", @@ -1382,6 +1521,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", + "id": "F06.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "낮다", "subcategory": "인터넷", @@ -1392,6 +1532,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", + "id": "F06.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "높다", "subcategory": "인터넷", @@ -1402,6 +1543,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", + "id": "F06.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", "severity": "높다", "subcategory": "인터넷", @@ -1413,6 +1555,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "id": "F06.10", "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", "severity": "높다", "subcategory": "인터넷", @@ -1423,6 +1566,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "id": "F06.11", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "높다", "subcategory": "인터넷", @@ -1433,6 +1577,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "id": "F06.12", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "높다", "subcategory": "인터넷", @@ -1443,6 +1588,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "id": "F06.13", "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", "severity": "높다", "subcategory": "인터넷", @@ -1453,6 +1599,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F06.14", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "severity": "높다", "subcategory": "인터넷", @@ -1462,6 +1609,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "F07.01", "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "severity": "높다", "subcategory": "파스 보안", @@ -1472,6 +1620,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", + "id": "F07.02", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "보통", "subcategory": "파스 보안", @@ -1482,6 +1631,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", + "id": "F07.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "보통", "subcategory": "파스 보안", @@ -1493,6 +1643,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F07.04", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "보통", "subcategory": "파스 보안", @@ -1503,6 +1654,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", + "id": "F07.05", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "보통", "subcategory": "파스 보안", @@ -1514,6 +1666,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F08.01", "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", "severity": "높다", "subcategory": "세분화", @@ -1524,6 +1677,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F08.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", "severity": "높다", "subcategory": "세분화", @@ -1534,6 +1688,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F08.03", "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", "severity": "보통", "subcategory": "세분화", @@ -1543,6 +1698,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", + "id": "F08.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", "severity": "보통", "subcategory": "세분화", @@ -1553,6 +1709,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", + "id": "F08.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "보통", "subcategory": "세분화", @@ -1564,6 +1721,7 @@ "category": "네트워크 토폴로지 및 연결", "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": "F08.06", "severity": "보통", "subcategory": "세분화", "text": "애플리케이션 팀은 서브넷 수준 NSG에서 애플리케이션 보안 그룹을 사용하여 랜딩 존 내의 다중 계층 VM을 보호해야 합니다.", @@ -1573,6 +1731,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", + "id": "F08.07", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "보통", "subcategory": "세분화", @@ -1583,6 +1742,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "dfe237de-143b-416c-91d7-aa9b64704489", + "id": "F08.08", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "보통", "subcategory": "세분화", @@ -1593,6 +1753,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", + "id": "F09.01", "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", "severity": "보통", "subcategory": "가상 WAN", @@ -1603,6 +1764,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", + "id": "F09.02", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "보통", "subcategory": "가상 WAN", @@ -1612,6 +1774,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", + "id": "F09.03", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "낮다", "subcategory": "가상 WAN", @@ -1622,6 +1785,7 @@ "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", + "id": "F09.04", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "보통", "subcategory": "가상 WAN", @@ -1632,6 +1796,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "id": "F09.05", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "보통", "subcategory": "가상 WAN", @@ -1641,6 +1806,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "id": "F09.06", "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", "severity": "보통", "subcategory": "가상 WAN", @@ -1650,6 +1816,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "id": "F09.07", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", "severity": "보통", "subcategory": "가상 WAN", @@ -1659,6 +1826,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "id": "F09.08", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", "severity": "보통", "subcategory": "가상 WAN", @@ -1668,6 +1836,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "id": "F09.09", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", "severity": "보통", "subcategory": "가상 WAN", @@ -1677,6 +1846,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "9c75dfef-573c-461c-a698-68598595581a", + "id": "F09.10", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", "severity": "높다", "subcategory": "가상 WAN", @@ -1686,6 +1856,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "G01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "높다", "subcategory": "앱 제공", @@ -1695,6 +1866,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "G01.02", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "보통", "subcategory": "앱 제공", @@ -1704,6 +1876,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "G01.03", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "높다", "subcategory": "앱 제공", @@ -1713,6 +1886,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "G01.04", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "높다", "subcategory": "앱 제공", @@ -1722,6 +1896,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "G01.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "높다", "subcategory": "앱 제공", @@ -1731,6 +1906,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "G01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "높다", "subcategory": "앱 제공", @@ -1740,6 +1916,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "G01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "높다", "subcategory": "앱 제공", @@ -1749,6 +1926,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "G01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "보통", "subcategory": "앱 제공", @@ -1758,6 +1936,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "G01.09", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "보통", "subcategory": "앱 제공", @@ -1767,6 +1946,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "G01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "보통", "subcategory": "앱 제공", @@ -1776,6 +1956,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "G01.11", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "낮다", "subcategory": "앱 제공", @@ -1785,6 +1966,7 @@ { "category": "네트워크 토폴로지 및 연결", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "G01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "보통", "subcategory": "앱 제공", @@ -1794,7 +1976,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", "severity": "높다", "subcategory": "DevOps 팀 토폴로지", "text": "Azure Landing Zone 아키텍처를 빌드, 관리 및 유지 관리할 수 있는 교차 기능 DevOps 플랫폼 팀이 있는지 확인합니다.", @@ -1803,7 +1986,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "낮다", "subcategory": "DevOps 팀 토폴로지", "text": "Azure 랜딩 존 플랫폼 팀을 위한 함수를 정의하는 것을 목표로 합니다.", @@ -1812,7 +1996,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "낮다", "subcategory": "DevOps 팀 토폴로지", "text": "애플리케이션 워크로드 팀이 자급자족하고 DevOps 플랫폼 팀 지원이 필요하지 않도록 기능을 정의하는 것을 목표로 합니다. 사용자 지정 RBAC 역할을 사용하여 이 작업을 수행합니다.", @@ -1821,7 +2006,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "165eb5e9-b434-448a-9e24-178632186212", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H01.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "높다", "subcategory": "DevOps 팀 토폴로지", "text": "CI/CD 파이프라인을 사용하여 IaC 아티팩트를 배포하고 배포 및 Azure 환경의 품질을 보장합니다.", @@ -1830,7 +2016,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "보통", "subcategory": "DevOps 팀 토폴로지", "text": "빌드 프로세스의 일부로 IaC 및 애플리케이션 코드에 대한 단위 테스트를 포함합니다.", @@ -1839,7 +2026,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "높다", "subcategory": "DevOps 팀 토폴로지", "text": "Key Vault 비밀을 사용하여 자격 증명(가상 머신 사용자 암호), 인증서 또는 키와 같은 중요한 정보를 하드 코딩하지 않도록 합니다.", @@ -1848,7 +2036,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", "severity": "낮다", "subcategory": "DevOps 팀 토폴로지", "text": "애플리케이션 및 워크로드를 위한 File > New > Landing Zone에 대한 자동화를 구현합니다.", @@ -1857,7 +2046,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "높다", "subcategory": "개발 라이프사이클", "text": "버전 제어 시스템이 애플리케이션 및 개발된 IaC의 소스 코드에 사용되는지 확인합니다. Microsoft는 Git을 권장합니다.", @@ -1866,7 +2056,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "낮다", "subcategory": "개발 라이프사이클", "text": "팀이 더 잘 협업하고 IaC 및 애플리케이션 코드의 버전 제어를 효율적으로 관리할 수 있도록 하는 분기 전략을 따릅니다. Github Flow와 같은 옵션을 검토합니다.", @@ -1875,7 +2066,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "보통", "subcategory": "개발 라이프사이클", "text": "분기에 병합된 코드 변경 내용을 계속 제어할 수 있도록 끌어오기 요청 전략을 채택합니다.", @@ -1884,7 +2076,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "높다", "subcategory": "개발 전략", "text": "Azure Bicep, ARM 템플릿 또는 Terraform과 같은 선언적 IaaS(Infrastructure as Code) 도구를 활용하여 Azure 랜딩 존 아키텍처를 빌드하고 유지 관리합니다. 플랫폼 및 응용 프로그램 워크로드 관점 모두에서.", @@ -1893,7 +2086,8 @@ { "category": "플랫폼 자동화 및 DevOps", "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", + "id": "H04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", "severity": "높다", "subcategory": "안전", "text": " DevOps에서 이미 결합된 개발 및 운영 프로세스에 보안을 통합하여 혁신 프로세스의 위험을 완화합니다.", @@ -1902,6 +2096,7 @@ { "category": "자원 조직", "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", + "id": "I01.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", "severity": "높다", "subcategory": "이름 지정 및 태깅", @@ -1912,6 +2107,7 @@ "category": "자원 조직", "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": "I02.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "보통", "subcategory": "구독", @@ -1923,6 +2119,7 @@ "category": "자원 조직", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", + "id": "I02.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", "severity": "보통", "subcategory": "구독", @@ -1933,6 +2130,7 @@ { "category": "자원 조직", "guid": "667313b4-f566-44b5-b984-a859c773e7d2", + "id": "I02.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "보통", "subcategory": "구독", @@ -1943,6 +2141,7 @@ { "category": "자원 조직", "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", + "id": "I02.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "보통", "subcategory": "구독", @@ -1953,6 +2152,7 @@ { "category": "자원 조직", "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", + "id": "I02.05", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "보통", "subcategory": "구독", @@ -1964,6 +2164,7 @@ "category": "자원 조직", "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": "I02.06", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", "severity": "보통", "subcategory": "구독", @@ -1973,6 +2174,7 @@ { "category": "자원 조직", "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", + "id": "I02.07", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "severity": "보통", "subcategory": "구독", @@ -1982,6 +2184,7 @@ { "category": "자원 조직", "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", + "id": "I02.08", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "보통", "subcategory": "구독", @@ -1991,6 +2194,7 @@ { "category": "자원 조직", "guid": "49b82111-2df2-47ee-912e-7f983f630472", + "id": "I02.09", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "높다", "subcategory": "구독", @@ -2000,6 +2204,7 @@ { "category": "자원 조직", "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", + "id": "I02.10", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "보통", "subcategory": "구독", @@ -2009,6 +2214,7 @@ { "category": "자원 조직", "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", + "id": "I02.11", "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", "severity": "높다", "subcategory": "구독", @@ -2019,6 +2225,7 @@ { "category": "자원 조직", "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", + "id": "I02.12", "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", "severity": "높다", "subcategory": "구독", @@ -2029,6 +2236,7 @@ { "category": "자원 조직", "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "I02.13", "link": "https://azure.microsoft.com/global-infrastructure/services/", "severity": "보통", "subcategory": "구독", @@ -2039,6 +2247,7 @@ { "category": "자원 조직", "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "I02.14", "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", "severity": "높다", "subcategory": "구독", @@ -2049,6 +2258,7 @@ { "category": "자원 조직", "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "I02.15", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "보통", "subcategory": "구독", @@ -2060,6 +2270,7 @@ "category": "자원 조직", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", + "id": "I02.16", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", "severity": "보통", "subcategory": "구독", @@ -2070,6 +2281,7 @@ { "category": "안전", "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", + "id": "J01.01", "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "severity": "보통", "subcategory": "출입 통제", @@ -2079,6 +2291,7 @@ { "category": "안전", "guid": "01365d38-e43f-49cc-ad86-8266abca264f", + "id": "J01.02", "link": "https://www.microsoft.com/security/business/zero-trust", "severity": "보통", "subcategory": "출입 통제", @@ -2088,6 +2301,7 @@ { "category": "안전", "guid": "5017f154-e3ab-4369-9829-e7e316183687", + "id": "J02.01", "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "severity": "높다", "subcategory": "암호화 및 키", @@ -2098,6 +2312,7 @@ "category": "안전", "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": "J02.02", "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "severity": "보통", "subcategory": "암호화 및 키", @@ -2107,6 +2322,7 @@ { "category": "안전", "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", + "id": "J02.03", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2116,6 +2332,7 @@ { "category": "안전", "guid": "dc055bcf-619e-48a1-9f98-879525d62688", + "id": "J02.04", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2125,6 +2342,7 @@ { "category": "안전", "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "J02.05", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2134,6 +2352,7 @@ { "category": "안전", "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "J02.06", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2143,6 +2362,7 @@ { "category": "안전", "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", + "id": "J02.07", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2152,6 +2372,7 @@ { "category": "안전", "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", + "id": "J02.08", "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", "severity": "보통", "subcategory": "암호화 및 키", @@ -2161,6 +2382,7 @@ { "category": "안전", "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", + "id": "J02.09", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2170,6 +2392,7 @@ { "category": "안전", "guid": "16183687-a047-47a2-8994-5bda43334f24", + "id": "J02.10", "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", "severity": "보통", "subcategory": "암호화 및 키", @@ -2179,6 +2402,7 @@ { "category": "안전", "guid": "91163418-2ba5-4275-8694-4008be7d7e48", + "id": "J02.11", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2188,6 +2412,7 @@ { "category": "안전", "guid": "25d62688-6d70-4ba6-a97b-e99519048384", + "id": "J02.12", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "보통", "subcategory": "암호화 및 키", @@ -2197,6 +2422,7 @@ { "category": "안전", "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", + "id": "J03.01", "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "severity": "보통", "subcategory": "작업", @@ -2206,6 +2432,7 @@ { "category": "안전", "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", + "id": "J03.02", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "severity": "보통", "subcategory": "작업", @@ -2215,15 +2442,47 @@ { "category": "안전", "guid": "09945bda-4333-44f2-9911-634182ba5275", - "link": "https://learn.microsoft.com/azure/security-center/", - "severity": "보통", + "id": "J03.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", + "severity": "높다", + "subcategory": "작업", + "text": "모든 구독에 대해 Defender 클라우드 보안 태세 관리를 사용하도록 설정합니다.", + "waf": "안전" + }, + { + "category": "안전", + "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", + "id": "J03.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", + "severity": "높다", + "subcategory": "작업", + "text": "모든 구독에서 서버에 대한 Defender 클라우드 워크로드 보호 계획을 사용하도록 설정합니다.", + "waf": "안전" + }, + { + "category": "안전", + "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", + "id": "J03.05", + "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", + "severity": "높다", + "subcategory": "작업", + "text": "모든 구독에서 Azure 리소스에 대한 Defender 클라우드 워크로드 보호 계획을 사용하도록 설정합니다.", + "waf": "안전" + }, + { + "category": "안전", + "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", + "id": "J03.06", + "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection", + "severity": "높다", "subcategory": "작업", - "text": "모든 구독에 대해 Defender for Cloud Standard를 사용하도록 설정합니다.", + "text": "IaaS 서버에서 Endpoint Protection을 사용하도록 설정합니다.", "waf": "안전" }, { "category": "안전", "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "J03.07", "link": "https://learn.microsoft.com/azure/security-center/", "severity": "보통", "subcategory": "작업", @@ -2233,6 +2492,7 @@ { "category": "안전", "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", + "id": "J03.08", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "보통", "subcategory": "작업", @@ -2242,6 +2502,7 @@ { "category": "안전", "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", + "id": "J04.01", "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", "severity": "높다", "subcategory": "개요", @@ -2251,6 +2512,7 @@ { "category": "안전", "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", + "id": "J04.02", "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", "severity": "높다", "subcategory": "개요", @@ -2260,16 +2522,17 @@ { "category": "안전", "guid": "6f704104-85c1-441f-96d3-c9819911645e", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/roles/security-planning", + "id": "J05.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning", "severity": "높다", "subcategory": "권한 있는 액세스 보호Secure privileged access", "text": "Azure 관리 작업에 대한 권한이 부여된 관리자 계정을 분리합니다.", - "training": "", "waf": "안전" }, { "category": "안전", "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", + "id": "J06.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "보통", "subcategory": "서비스 지원 프레임워크", @@ -2279,6 +2542,7 @@ { "category": "안전", "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", + "id": "J06.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "보통", "subcategory": "서비스 지원 프레임워크", @@ -2289,7 +2553,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "September 07, 2023" + "timestamp": "September 14, 2023" }, "severities": [ { diff --git a/checklists/alz_checklist.pt.json b/checklists/alz_checklist.pt.json index 14a089678..3f3d4de76 100644 --- a/checklists/alz_checklist.pt.json +++ b/checklists/alz_checklist.pt.json @@ -29,17 +29,19 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "70c15989-c726-42c7-b0d3-24b7375b9201", - "link": "https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/considerations/tenancy-models", + "id": "A01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/considerations-recommendations", "severity": "Média", "subcategory": "Locatários do Azure AD", - "text": "Quantos locatários do Azure AD você gerencia?", + "text": "Use um locatário do Entra para gerenciar seus recursos do Azure, a menos que você tenha um requisito regulamentar ou comercial claro para multilocatários.", "waf": "Operações" }, { "category": "Locatário do Azure e do Active Directory", "guid": "6309957b-821a-43d1-b9d9-7fcf1802b747", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", - "severity": "Média", + "id": "A01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/automation", + "severity": "Baixo", "subcategory": "Locatários do Azure AD", "text": "Verifique se você tem uma abordagem de Automação Multilocatário para gerenciar seus Locatários do Azure AD", "waf": "Operações" @@ -47,8 +49,9 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "78e11934-499a-45ed-8ef7-aae5578f0ecf", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", - "severity": "Média", + "id": "A01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/multi-tenant/lighthouse", + "severity": "Baixo", "subcategory": "Locatários do Azure AD", "text": "Aproveite o Farol do Azure para gerenciamento multilocatário", "waf": "Operações" @@ -56,7 +59,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "5d82e6df-6f61-42f2-82e2-3132d293be3d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Média", "subcategory": "Provedor de Soluções na Nuvem", "text": "Verifique se o Farol do Azure é usado para administrar o locatário por parceiro", @@ -65,7 +69,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "a24d0de3-d4b9-4dfb-8ddd-bbfaf123fa01", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Baixo", "subcategory": "Provedor de Soluções na Nuvem", "text": "Discutir a solicitação de suporte e o processo de escalonamento com o parceiro CSP", @@ -74,7 +79,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "32952499-58c8-4e6f-ada5-972e67893d55", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Média", "subcategory": "Provedor de Soluções na Nuvem", "text": "Configurar relatórios de custos e exibições com o Gerenciamento de Custos do Azure", @@ -83,7 +89,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "685cb4f2-ac9c-4b19-9167-993ed0b32415", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", + "id": "A03.01", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/direct-ea-administration#manage-notification-contacts", "severity": "Média", "subcategory": "Acordo de Empresa", "text": "Configurar contatos de notificação para uma caixa de correio de grupo", @@ -92,7 +99,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "12cd499f-96e2-4e41-a243-231fb3245a1c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Baixo", "subcategory": "Acordo de Empresa", "text": "Usar departamentos e contas para mapear a estrutura da sua organização para a hierarquia de inscrição pode ajudar na separação do faturamento.", @@ -101,7 +109,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "29213165-f066-46c4-81fc-4214cc19f3d0", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Alto", "subcategory": "Acordo de Empresa", "text": "Verifique se as Contas estão configuradas para serem do tipo 'Conta corporativa e de estudante'", @@ -110,7 +119,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "ca0fe401-12ad-46fc-8a7e-86293866a9f6", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Média", "subcategory": "Acordo de Empresa", "text": "Habilite os Encargos de Exibição de DA e os Encargos de Exibição de AO em suas Inscrições EA para permitir que os usuários com os dados de Custo e Faturamento de revisão de perms corretos.", @@ -119,7 +129,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "5cf9f485-2784-49b3-9824-75d9b8bdb57b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Baixo", "subcategory": "Acordo de Empresa", "text": "Faça uso de assinaturas corporativas de desenvolvimento/teste para reduzir os custos de cargas de trabalho que não são de produção", @@ -128,7 +139,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "2cf08656-13ea-4f7e-a53a-e2c956b1ff6c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", + "id": "A03.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-enterprise-agreement#design-considerations", "severity": "Média", "subcategory": "Acordo de Empresa", "text": "Auditar periodicamente as atribuições de função para revisar quem tem acesso ao seu Registro no Enterprise Agreement", @@ -137,7 +149,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "6ad5c3dd-e5ea-4ff1-81a4-7886ff87845c", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Baixo", "subcategory": "Contrato de Nuvem da Microsoft", "text": "Configurar email de contato de notificação de conta de faturamento do contrato", @@ -146,7 +159,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "90e87802-602f-4dfb-acea-67c60689f1d7", - "link": "https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/mca-section-invoice", + "id": "A04.02", + "link": "https://learn.microsoft.com/azure/cost-management-billing/manage/mca-section-invoice", "severity": "Baixo", "subcategory": "Contrato de Nuvem da Microsoft", "text": "Use as seções Perfis de faturamento e Fatura para estruturar o faturamento de seus contratos para um gerenciamento de custos eficaz", @@ -155,7 +169,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "e81a73f0-84c4-4641-b406-14db3b4d1f50", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Baixo", "subcategory": "Contrato de Nuvem da Microsoft", "text": "Fazer uso do Plano do Azure para reduzir custos para cargas de trabalho que não são de produção", @@ -164,7 +179,8 @@ { "category": "Locatário do Azure e do Active Directory", "guid": "ae757485-92a4-482a-8bc9-eefe6f5b5ec3", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", + "id": "A04.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/azure-billing-microsoft-customer-agreement#design-recommendations", "severity": "Média", "subcategory": "Contrato de Nuvem da Microsoft", "text": "Audite periodicamente as atribuições de função RBAC de faturamento do contrato para analisar quem tem acesso à sua conta de faturamento MCA", @@ -173,6 +189,7 @@ { "category": "Governança", "guid": "5c986cb2-9131-456a-8247-6e49f541acdc", + "id": "B01.01", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Alto", "subcategory": "Governança", @@ -182,6 +199,7 @@ { "category": "Governança", "guid": "e979377b-cdb3-4751-ab2a-b13ada6e55d7", + "id": "B01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging", "severity": "Média", "subcategory": "Governança", @@ -191,6 +209,7 @@ { "category": "Governança", "guid": "d8a2adb1-17d6-4326-af62-5ca44e5695f2", + "id": "B01.03", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Média", "subcategory": "Governança", @@ -200,6 +219,7 @@ { "category": "Governança", "guid": "223ace8c-b123-408c-a501-7f154e3ab369", + "id": "B01.04", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Média", "subcategory": "Governança", @@ -209,6 +229,7 @@ { "category": "Governança", "guid": "3829e7e3-1618-4368-9a04-77a209945bda", + "id": "B01.05", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Média", "subcategory": "Governança", @@ -218,6 +239,7 @@ { "category": "Governança", "guid": "43334f24-9116-4341-a2ba-527526944008", + "id": "B01.06", "link": "https://learn.microsoft.com/security/benchmark/azure/mcsb-asset-management#am-2-use-only-approved-services", "severity": "Baixo", "subcategory": "Governança", @@ -227,6 +249,7 @@ { "category": "Governança", "guid": "be7d7e48-4327-46d8-adc0-55bcf619e8a1", + "id": "B01.07", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Média", "subcategory": "Governança", @@ -237,6 +260,7 @@ "category": "Governança", "description": "A atribuição da função Colaborador de Política de Recursos a escopos específicos permite delegar o gerenciamento de políticas a equipes relevantes. Por exemplo, uma equipe central de TI pode supervisionar políticas de nível de grupo de gerenciamento, enquanto as equipes de aplicativos lidam com políticas para suas assinaturas, permitindo a governança distribuída com aderência aos padrões organizacionais.", "guid": "3f988795-25d6-4268-a6d7-0ba6c97be995", + "id": "B01.08", "link": "https://learn.microsoft.com/azure/governance/policy/overview#azure-rbac-permissions-in-azure-policy", "severity": "Média", "subcategory": "Governança", @@ -246,6 +270,7 @@ { "category": "Governança", "guid": "19048384-5c98-46cb-8913-156a12476e49", + "id": "B01.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Média", "subcategory": "Governança", @@ -255,7 +280,8 @@ { "category": "Governança", "guid": "9b5e2a28-9823-4faf-ab7e-afa5f6c57221", - "link": "https://learn.microsoft.com/en-us/azure/automation/automation-solution-vm-management-config", + "id": "B02.01", + "link": "https://learn.microsoft.com/azure/automation/automation-solution-vm-management-config", "severity": "Baixo", "subcategory": "Otimize seu investimento em nuvem", "text": "Considere o uso de tags de automação para iniciar/parar VMs em seu ambiente para economizar custos.", @@ -264,7 +290,8 @@ { "category": "Governança", "guid": "29fd366b-a180-452b-9bd7-954b7700c667", - "link": "https://learn.microsoft.com/en-us/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", + "id": "B02.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", "severity": "Média", "subcategory": "Otimize seu investimento em nuvem", "text": "Configure alertas de orçamento 'Real' e 'Previsto'.", @@ -273,16 +300,18 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "4348bf81-7573-4512-8f46-9061cc198fea", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#identity-and-access-management-in-the-azure-landing-zone-accelerator", + "id": "C01.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", "severity": "Alto", "subcategory": "Active Directory e identidade híbrida", "text": "Usar identidades gerenciadas em vez de entidades de serviço para autenticação nos serviços do Azure", - "training": "https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview", + "training": "https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview", "waf": "Segurança" }, { "category": "Gerenciamento de identidades e acesso", "guid": "cd163e39-84a5-4b39-97b7-6973abd70d94", + "id": "C02.01", "link": "https://learn.microsoft.com/azure/active-directory/hybrid/how-to-connect-sync-staging-server", "severity": "Média", "subcategory": "Azure AD", @@ -292,6 +321,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "984a859c-773e-47d2-9162-3a765a917e1f", + "id": "C03.01", "link": "https://learn.microsoft.com/azure/active-directory/roles/security-emergency-access", "severity": "Alto", "subcategory": "Identidade", @@ -302,16 +332,17 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "1cf0b8da-70bd-44d0-94af-8d99cfc89ae1", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", + "id": "C03.02", + "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/concept-activity-logs-azure-monitor", "severity": "Média", "subcategory": "Identidade", "text": "Integre os logs do Azure AD com o Azure Monitor central de plataforma. O Azure Monitor permite uma única fonte de verdade sobre dados de log e monitoramento no Azure, oferecendo às organizações opções nativas de nuvem para atender aos requisitos de coleta e retenção de logs.", - "training": "", "waf": "Segurança" }, { "category": "Gerenciamento de identidades e acesso", "guid": "348ef254-c27d-442e-abba-c7571559ab91", + "id": "C03.03", "link": "https://learn.microsoft.com/azure/role-based-access-control/overview", "severity": "Alto", "subcategory": "Identidade", @@ -322,6 +353,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "53e8908a-e28c-484c-93b6-b7808b9fe5c4", + "id": "C03.04", "link": "https://learn.microsoft.com/azure/active-directory/conditional-access/overview", "severity": "Baixo", "subcategory": "Identidade", @@ -332,6 +364,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "1049d403-a923-4c34-94d0-0018ac6a9e01", + "id": "C03.05", "link": "https://learn.microsoft.com/azure/active-directory/authentication/concept-mfa-howitworks", "severity": "Alto", "subcategory": "Identidade", @@ -342,6 +375,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "e6a83de5-de32-4c19-a248-1607d5d1e4e6", + "id": "C03.06", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/manage/centralize-operations", "severity": "Média", "subcategory": "Identidade", @@ -352,6 +386,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "14658d35-58fd-4772-99b8-21112df27ee4", + "id": "C03.07", "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-configure", "severity": "Média", "subcategory": "Identidade", @@ -362,6 +397,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "12e7f983-f630-4472-8dd6-9c5b5c2622f5", + "id": "C03.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", "severity": "Alto", "subcategory": "Identidade", @@ -372,6 +408,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "4b69bad3-3aad-45e8-a68e-1d76667313b4", + "id": "C03.09", "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-groups-create-azure-portal", "severity": "Média", "subcategory": "Identidade", @@ -382,6 +419,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "f5664b5e-984a-4859-a773-e7d261623a76", + "id": "C03.10", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access#prerequisites-for-a-landing-zone---design-recommendations", "severity": "Média", "subcategory": "Identidade", @@ -392,6 +430,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "5a917e1f-348e-4f25-9c27-d42e8bbac757", + "id": "C03.11", "link": "https://azure.microsoft.com/resources/achieving-compliant-data-residency-and-security-with-azure/", "severity": "Média", "subcategory": "Identidade", @@ -402,6 +441,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "1559ab91-53e8-4908-ae28-c84c33b6b780", + "id": "C03.12", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "Média", "subcategory": "Identidade", @@ -412,6 +452,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "8b9fe5c4-1049-4d40-9a92-3c3474d00018", + "id": "C03.13", "link": "https://learn.microsoft.com/azure/active-directory-domain-services/overview", "severity": "Média", "subcategory": "Identidade", @@ -422,6 +463,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "ac6a9e01-e6a8-43de-9de3-2c1992481607", + "id": "C03.14", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain", "severity": "Média", "subcategory": "Identidade", @@ -432,6 +474,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "d5d1e4e6-1465-48d3-958f-d77249b82111", + "id": "C03.15", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy", "severity": "Média", "subcategory": "Identidade", @@ -442,6 +485,7 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "35037e68-9349-4c15-b371-228514f4cdff", + "id": "C03.16", "link": "https://learn.microsoft.com/azure/active-directory/roles/best-practices", "severity": "Média", "subcategory": "Identidade", @@ -452,36 +496,39 @@ { "category": "Gerenciamento de identidades e acesso", "guid": "9cf5418b-1520-4b7b-add7-88eb28f833e8", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", + "id": "C04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#managed-identities", "severity": "Baixo", "subcategory": "Zonas de desembarque", "text": "Configure a segmentação de rede de identidade (ADDS) por meio do uso de uma rede virtual e faça peer back para o hub. Fornecendo autenticação dentro da zona de aterrissagem do aplicativo (legado).", - "training": "https://learn.microsoft.com/en-us/azure/architecture/example-scenario/identity/adds-extend-domain", + "training": "https://learn.microsoft.com/azure/architecture/example-scenario/identity/adds-extend-domain", "waf": "Segurança" }, { "category": "Gerenciamento de identidades e acesso", "guid": "d4d1ad54-1abc-4919-b267-3f342d3b49e4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", + "id": "C04.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/identity-access-landing-zones#rbac-recommendations", "severity": "Média", "subcategory": "Zonas de desembarque", "text": "Use o RBAC do Azure para gerenciar o acesso do plano de dados aos recursos, se possível. E.G - Operações de dados em Keyvault, Conta de armazenamento e serviços de banco de dados. ", - "training": "https://learn.microsoft.com/en-us/azure/role-based-access-control/overview", + "training": "https://learn.microsoft.com/azure/role-based-access-control/overview", "waf": "Segurança" }, { "category": "Gerenciamento de identidades e acesso", "guid": "d505ebcb-79b1-4274-9c0d-a27c8bea489c", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", + "id": "C04.03", + "link": "https://learn.microsoft.com/azure/active-directory/privileged-identity-management/pim-create-roles-and-resource-roles-review", "severity": "Média", "subcategory": "Zonas de desembarque", "text": "Use as revisões de acesso do Azure AD PIM para validar periodicamente os direitos de recurso.", - "training": "", "waf": "Segurança" }, { "category": "Gestão", "guid": "89cc5e11-aa4d-4c3b-893d-feb99215266a", + "id": "D01.01", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-diagnostic-settings-to-save-your-wafs-logs", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -491,6 +538,7 @@ { "category": "Gestão", "guid": "7f408960-c626-44cb-a018-347c8d790cdf", + "id": "D01.02", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#send-logs-to-microsoft-sentinel", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -500,6 +548,7 @@ { "category": "Gestão", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", + "id": "D02.01", "link": "https://learn.microsoft.com/azure/reliability/cross-region-replication-azure", "severity": "Média", "subcategory": "Proteção de Dados", @@ -509,6 +558,7 @@ { "category": "Gestão", "guid": "eba8cf22-45c6-4dc1-9b57-2cceb3b97ce5", + "id": "D02.02", "link": "https://learn.microsoft.com/azure/storage/common/storage-redundancy", "severity": "Média", "subcategory": "Proteção de Dados", @@ -518,6 +568,7 @@ { "category": "Gestão", "guid": "67e7a8ed-4b30-4e38-a3f2-9812b2363cef", + "id": "D03.01", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Média", "subcategory": "Monitorização", @@ -528,6 +579,7 @@ { "category": "Gestão", "guid": "e179b599-de0d-4597-9cd4-cd21b088137f", + "id": "D03.02", "severity": "Média", "subcategory": "Monitorização", "text": "A zona de pouso está documentada?", @@ -536,7 +588,8 @@ { "category": "Gestão", "guid": "5e6c4cfd-3e50-4454-9c24-47ec66138a72", - "link": "https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", + "id": "D03.03", + "link": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-archive?tabs=portal-1%2Cportal-2#how-retention-and-archiving-work", "severity": "Média", "subcategory": "Monitorização", "text": "Use os Logs do Azure Monitor quando os requisitos de retenção de log excederem dois anos. Atualmente, você pode manter os dados arquivados por até 7 anos.", @@ -546,6 +599,7 @@ { "category": "Gestão", "guid": "00f1ce16-ed30-41d6-b872-e52e3611cc58", + "id": "D03.04", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Média", "subcategory": "Monitorização", @@ -556,6 +610,7 @@ { "category": "Gestão", "guid": "e7d7e484-3276-4d8b-bc05-5bcf619e8a13", + "id": "D03.05", "link": "https://learn.microsoft.com/azure/governance/policy/how-to/guest-configuration-create", "severity": "Média", "subcategory": "Monitorização", @@ -566,6 +621,7 @@ { "category": "Gestão", "guid": "f9887952-5d62-4688-9d70-ba6c97be9951", + "id": "D03.06", "link": "https://learn.microsoft.com/azure/automation/update-management/overview", "severity": "Média", "subcategory": "Monitorização", @@ -576,6 +632,7 @@ { "category": "Gestão", "guid": "90483845-c986-4cb2-a131-56a12476e49f", + "id": "D03.07", "link": "https://learn.microsoft.com/azure/network-watcher/network-watcher-monitoring-overview", "severity": "Média", "subcategory": "Monitorização", @@ -586,6 +643,7 @@ { "category": "Gestão", "guid": "541acdce-9793-477b-adb3-751ab2ab13ad", + "id": "D03.08", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/lock-resources?tabs=json", "severity": "Média", "subcategory": "Monitorização", @@ -596,6 +654,7 @@ { "category": "Gestão", "guid": "a6e55d7d-8a2a-4db1-87d6-326af625ca44", + "id": "D03.09", "link": "https://learn.microsoft.com/azure/governance/policy/overview", "severity": "Baixo", "subcategory": "Monitorização", @@ -605,6 +664,7 @@ { "category": "Gestão", "guid": "e5695f22-23ac-4e8c-a123-08ca5017f154", + "id": "D03.10", "link": "https://learn.microsoft.com/azure/service-health/alerts-activity-log-service-notifications-portal", "severity": "Média", "subcategory": "Monitorização", @@ -614,6 +674,7 @@ { "category": "Gestão", "guid": "d5f345bf-97ab-41a7-819c-6104baa7d48c", + "id": "D03.11", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups", "severity": "Média", "subcategory": "Monitorização", @@ -623,6 +684,7 @@ { "category": "Gestão", "guid": "e3ab3693-829e-47e3-8618-3687a0477a20", + "id": "D03.12", "link": "https://learn.microsoft.com/azure/sentinel/quickstart-onboard", "severity": "Média", "subcategory": "Monitorização", @@ -632,6 +694,7 @@ { "category": "Gestão", "guid": "9945bda4-3334-4f24-a116-34182ba52752", + "id": "D03.13", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Média", "subcategory": "Monitorização", @@ -641,6 +704,7 @@ { "category": "Gestão", "guid": "6944008b-e7d7-4e48-9327-6d8bdc055bcf", + "id": "D03.14", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-setup-guide/monitoring-reporting?tabs=AzureMonitor", "severity": "Média", "subcategory": "Monitorização", @@ -650,6 +714,7 @@ { "category": "Gestão", "guid": "619e8a13-f988-4795-85d6-26886d70ba6c", + "id": "D03.15", "link": "https://learn.microsoft.com/azure/azure-monitor/agents/diagnostics-extension-overview", "severity": "Média", "subcategory": "Monitorização", @@ -659,6 +724,7 @@ { "category": "Gestão", "guid": "97be9951-9048-4384-9c98-6cb2913156a1", + "id": "D03.16", "link": "https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview", "severity": "Média", "subcategory": "Monitorização", @@ -668,6 +734,7 @@ { "category": "Gestão", "guid": "859c3900-4514-41eb-b010-475d695abd74", + "id": "D03.17", "link": "https://learn.microsoft.com/azure/architecture/best-practices/monitoring", "severity": "Média", "subcategory": "Monitorização", @@ -677,6 +744,7 @@ { "category": "Gestão", "guid": "fed3c55f-a67e-4875-aadd-3aba3f9fde31", + "id": "D03.18", "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings", "severity": "Média", "subcategory": "Monitorização", @@ -686,6 +754,7 @@ { "category": "Gestão", "guid": "f541acdc-e979-4377-acdb-3751ab2ab13a", + "id": "D04.01", "link": "https://learn.microsoft.com/azure/governance/policy/concepts/guest-configuration", "severity": "Média", "subcategory": "Compatibilidade operacional", @@ -696,6 +765,7 @@ "category": "Gestão", "description": "Os recursos de configuração de convidado da Política do Azure podem auditar e corrigir as configurações do computador (por exemplo, sistema operacional, aplicativo, ambiente) para garantir que os recursos estejam alinhados com as configurações esperadas, e o Gerenciamento de Atualizações pode impor o gerenciamento de patches para VMs.", "guid": "da6e55d7-d8a2-4adb-817d-6326af625ca4", + "id": "D04.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/management-operational-compliance#monitoring-for-configuration-drift", "severity": "Média", "subcategory": "Compatibilidade operacional", @@ -705,6 +775,7 @@ { "category": "Gestão", "guid": "2476e49f-541a-4cdc-b979-377bcdb3751a", + "id": "D05.01", "link": "https://learn.microsoft.com/azure/site-recovery/site-recovery-overview", "severity": "Média", "subcategory": "Proteja e recupere", @@ -714,6 +785,7 @@ { "category": "Gestão", "guid": "b2ab13ad-a6e5-45d7-b8a2-adb117d6326a", + "id": "D05.02", "link": "https://learn.microsoft.com/azure/architecture/framework/resiliency/backup-and-recovery", "severity": "Média", "subcategory": "Proteja e recupere", @@ -723,6 +795,7 @@ { "category": "Gestão", "guid": "f625ca44-e569-45f2-823a-ce8cb12308ca", + "id": "D05.03", "link": "https://learn.microsoft.com/azure/backup/backup-center-overview", "severity": "Média", "subcategory": "Proteja e recupere", @@ -732,6 +805,7 @@ { "category": "Gestão ", "guid": "826c5c45-bb79-4951-a812-e3bfbfd7326b", + "id": "E01.01", "link": "https://learn.microsoft.com/azure/reliability/availability-zones-overview", "severity": "Alto", "subcategory": "Tolerância a falhas", @@ -741,6 +815,7 @@ { "category": "Gestão ", "guid": "7ccb7c06-5511-42df-8177-d97f08d0337d", + "id": "E01.02", "link": "https://learn.microsoft.com/azure/virtual-machines/availability", "severity": "Alto", "subcategory": "Tolerância a falhas", @@ -750,6 +825,7 @@ { "category": "Gestão ", "guid": "84101f59-1941-4195-a270-e28034290e3a", + "id": "E01.03", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "Média", "subcategory": "Tolerância a falhas", @@ -759,6 +835,7 @@ { "category": "Gestão ", "guid": "ecdc7506-6f37-4ea9-be87-fc5d3df08a64", + "id": "E02.01", "link": "https://learn.microsoft.com/azure/virtual-machine-scale-sets/overview", "severity": "Média", "subcategory": "Escalabilidade", @@ -768,6 +845,7 @@ { "category": "Topologia de rede e conectividade", "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "id": "F01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -777,6 +855,7 @@ { "category": "Topologia de rede e conectividade", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", + "id": "F01.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-groups-in-the-azure-landing-zone-accelerator", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -788,6 +867,7 @@ "category": "Topologia de rede e conectividade", "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": "F01.03", "link": "https://learn.microsoft.com/azure/application-gateway/overview-v2", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -799,6 +879,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "id": "F01.04", "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -809,6 +890,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", "guid": "dfc50f87-3800-424c-937b-ed5f186e7c15", + "id": "F01.05", "link": "https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -820,6 +902,7 @@ "category": "Topologia de rede e conectividade", "description": "A administração de proxies reversos em geral e do WAF em particular está mais próxima do aplicativo do que da rede, portanto, eles pertencem à mesma assinatura do aplicativo. Centralizar o Application Gateway e o WAF na assinatura de conectividade pode ser OK se for gerenciado por uma única equipe.", "guid": "48b662d6-d15f-4512-a654-98f6dfe237de", + "id": "F01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -830,6 +913,7 @@ { "category": "Topologia de rede e conectividade", "guid": "143b16c3-1d7a-4a9b-9470-4489a8042d88", + "id": "F01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -840,6 +924,7 @@ { "category": "Topologia de rede e conectividade", "guid": "e79d17b7-3b22-4a5a-97e7-a8ed4b30e38c", + "id": "F01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -850,6 +935,7 @@ { "category": "Topologia de rede e conectividade", "guid": "3f29812b-2363-4cef-b179-b599de0d5973", + "id": "F01.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -860,6 +946,7 @@ { "category": "Topologia de rede e conectividade", "guid": "cd4cd21b-0881-437f-9e6c-4cfd3e504547", + "id": "F01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -870,6 +957,7 @@ { "category": "Topologia de rede e conectividade", "guid": "3b4b3e88-a459-4ed5-a22f-644dfbc58204", + "id": "F01.11", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Baixo", "subcategory": "Entrega de aplicativos", @@ -880,6 +968,7 @@ { "category": "Topologia de rede e conectividade", "guid": "01ca7cf1-5754-442d-babb-8ba6772e5c30", + "id": "F01.12", "link": "https://learn.microsoft.com/azure/active-directory/app-proxy/application-proxy#how-application-proxy-works", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -891,6 +980,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode", "guid": "ae248989-b306-4591-9186-de482e3f0f0e", + "id": "F01.13", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -900,6 +990,7 @@ { "category": "Topologia de rede e conectividade", "guid": "062d5839-4d36-402f-bfa4-02811eb936e9", + "id": "F01.14", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#avoid-combining-traffic-manager-and-front-door", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -909,6 +1000,7 @@ { "category": "Topologia de rede e conectividade", "guid": "5efeb96a-003f-4b18-8fcd-b4d84459c2b2", + "id": "F01.15", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-the-same-domain-name-on-front-door-and-your-origin", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -918,6 +1010,7 @@ { "category": "Topologia de rede e conectividade", "guid": "0b5a380c-4bfb-47bc-b1d7-dcfef363a61b", + "id": "F01.16", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#disable-health-probes-when-theres-only-one-origin-in-an-origin-group", "severity": "Baixo", "subcategory": "Entrega de aplicativos", @@ -927,6 +1020,7 @@ { "category": "Topologia de rede e conectividade", "guid": "5567048e-e5d7-4206-9c55-b5ed45d2cc0c", + "id": "F01.17", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#select-good-health-probe-endpoints", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -936,6 +1030,7 @@ { "category": "Topologia de rede e conectividade", "guid": "a13f72f3-8f5c-4864-95e5-75bf37fbbeb1", + "id": "F01.18", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-head-health-probes", "severity": "Baixo", "subcategory": "Entrega de aplicativos", @@ -946,6 +1041,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant", "guid": "97a2fd46-64b0-1dfa-b72d-9c8869496d75", + "id": "F01.19", "link": "https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -955,6 +1051,7 @@ { "category": "Topologia de rede e conectividade", "guid": "af95c92d-d723-4f4a-98d7-8722324efd4d", + "id": "F01.20", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-managed-tls-certificates", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -964,6 +1061,7 @@ { "category": "Topologia de rede e conectividade", "guid": "189ea962-3969-4863-8f5a-5ad808c2cf4b", + "id": "F01.21", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#define-your-waf-configuration-as-code", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -973,6 +1071,7 @@ { "category": "Topologia de rede e conectividade", "guid": "de0d5973-cd4c-4d21-a088-137f5e6c4cfd", + "id": "F02.01", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "Média", "subcategory": "Encriptação", @@ -982,6 +1081,7 @@ { "category": "Topologia de rede e conectividade", "guid": "ed301d6e-872e-452e-9611-cc58b5a4b151", + "id": "F02.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "Baixo", "subcategory": "Encriptação", @@ -992,6 +1092,7 @@ { "category": "Topologia de rede e conectividade", "guid": "e8bbac75-7155-49ab-a153-e8908ae28c84", + "id": "F03.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/enterprise-scale/network-topology-and-connectivity", "severity": "Média", "subcategory": "Hub e falou", @@ -1002,6 +1103,7 @@ { "category": "Topologia de rede e conectividade", "guid": "7dd61623-a364-4a90-9eca-e48ebd54cd7d", + "id": "F03.02", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/expressroute", "severity": "Alto", "subcategory": "Hub e falou", @@ -1011,6 +1113,7 @@ { "category": "Topologia de rede e conectividade", "guid": "e2e8abac-3571-4559-ab91-53e89f89dc7b", + "id": "F03.03", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/dmz/nva-ha", "severity": "Média", "subcategory": "Hub e falou", @@ -1020,6 +1123,7 @@ { "category": "Topologia de rede e conectividade", "guid": "ce463dbb-bc8a-4c2a-aebc-92a43da1dae2", + "id": "F03.04", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-coexist-resource-manager#to-enable-transit-routing-between-expressroute-and-azure-vpn", "severity": "Baixo", "subcategory": "Hub e falou", @@ -1030,6 +1134,7 @@ "category": "Topologia de rede e conectividade", "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": "F03.05", "link": "https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1", "severity": "Baixo", "subcategory": "Hub e falou", @@ -1039,6 +1144,7 @@ { "category": "Topologia de rede e conectividade", "guid": "cc881471-607c-41cc-a0e6-14658dd558f9", + "id": "F03.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", "severity": "Média", "subcategory": "Hub e falou", @@ -1049,6 +1155,7 @@ { "category": "Topologia de rede e conectividade", "guid": "4722d929-c1b1-4cd6-81f5-4b29bade39ad", + "id": "F03.07", "link": "https://learn.microsoft.com/azure/azure-monitor/insights/network-insights-overview", "severity": "Média", "subcategory": "Hub e falou", @@ -1060,6 +1167,7 @@ "category": "Topologia de rede e conectividade", "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": "F03.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", "severity": "Média", "subcategory": "Hub e falou", @@ -1070,6 +1178,7 @@ "category": "Topologia de rede e conectividade", "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": "F03.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", "severity": "Média", "subcategory": "Hub e falou", @@ -1080,6 +1189,7 @@ "category": "Topologia de rede e conectividade", "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": "F03.10", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering", "severity": "Alto", "subcategory": "Hub e falou", @@ -1089,6 +1199,7 @@ { "category": "Topologia de rede e conectividade", "guid": "359c373e-7dd6-4162-9a36-4a907ecae48e", + "id": "F04.01", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli", "severity": "Média", "subcategory": "Híbrido", @@ -1100,6 +1211,7 @@ "category": "Topologia de rede e conectividade", "description": "Você pode usar os pesos de conexão e prependente de caminho AS para influenciar o tráfego do Azure para o local e toda a gama de atributos BGP em seus próprios roteadores para influenciar o tráfego do local para o Azure.", "guid": "f29812b2-363c-4efe-879b-599de0d5973c", + "id": "F04.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "Média", "subcategory": "Híbrido", @@ -1111,6 +1223,7 @@ "category": "Topologia de rede e conectividade", "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": "F04.03", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-routing", "severity": "Média", "subcategory": "Híbrido", @@ -1122,6 +1235,7 @@ "category": "Topologia de rede e conectividade", "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": "F04.04", "link": "https://learn.microsoft.com/azure/expressroute/plan-manage-cost", "severity": "Alto", "subcategory": "Híbrido", @@ -1132,6 +1246,7 @@ "category": "Topologia de rede e conectividade", "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": "F04.05", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local", "severity": "Alto", "subcategory": "Híbrido", @@ -1142,6 +1257,7 @@ "category": "Topologia de rede e conectividade", "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": "F04.06", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways", "severity": "Média", "subcategory": "Híbrido", @@ -1152,6 +1268,7 @@ { "category": "Topologia de rede e conectividade", "guid": "72e52e36-11cc-458b-9a4b-1511e43a58a9", + "id": "F04.07", "link": "https://learn.microsoft.com/azure/networking/", "severity": "Média", "subcategory": "Híbrido", @@ -1162,6 +1279,7 @@ { "category": "Topologia de rede e conectividade", "guid": "c2299c4d-7b57-4d0c-9555-62f2b3e4563a", + "id": "F04.08", "link": "https://learn.microsoft.com/azure/expressroute/about-fastpath", "severity": "Média", "subcategory": "Híbrido", @@ -1173,6 +1291,7 @@ "category": "Topologia de rede e conectividade", "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": "F04.09", "link": "https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway", "severity": "Média", "subcategory": "Híbrido", @@ -1183,6 +1302,7 @@ { "category": "Topologia de rede e conectividade", "guid": "718cb437-b060-2589-8856-2e93a5c6633b", + "id": "F04.10", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-erdirect-about", "severity": "Alto", "subcategory": "Híbrido", @@ -1193,6 +1313,7 @@ { "category": "Topologia de rede e conectividade", "guid": "8042d88e-79d1-47b7-9b22-a5a67e7a8ed4", + "id": "F04.11", "link": "https://learn.microsoft.com/azure/architecture/framework/services/networking/expressroute/reliability", "severity": "Média", "subcategory": "Híbrido", @@ -1203,6 +1324,7 @@ { "category": "Topologia de rede e conectividade", "guid": "b30e38c3-f298-412b-8363-cefe179b599d", + "id": "F04.12", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-monitoring-metrics-alerts", "severity": "Média", "subcategory": "Híbrido", @@ -1213,6 +1335,7 @@ { "category": "Topologia de rede e conectividade", "guid": "5bf68dc9-325e-4873-bf88-f8214ef2e5d2", + "id": "F04.13", "link": "https://learn.microsoft.com/azure/expressroute/how-to-configure-connection-monitor", "severity": "Média", "subcategory": "Híbrido", @@ -1223,6 +1346,7 @@ { "category": "Topologia de rede e conectividade", "guid": "e0d5973c-d4cd-421b-8881-37f5e6c4cfd3", + "id": "F04.14", "link": "https://learn.microsoft.com/azure/expressroute/designing-for-disaster-recovery-with-expressroute-privatepeering#challenges-of-using-multiple-expressroute-circuits", "severity": "Média", "subcategory": "Híbrido", @@ -1233,6 +1357,7 @@ { "category": "Topologia de rede e conectividade", "guid": "2df4930f-6a43-49a3-926b-309f02c302f0", + "id": "F04.15", "link": "https://learn.microsoft.com/azure/architecture/reference-architectures/identity/adds-extend-domain#vm-recommendations", "severity": "Alto", "subcategory": "Híbrido", @@ -1242,6 +1367,7 @@ { "category": "Topologia de rede e conectividade", "guid": "558fd772-49b8-4211-82df-27ee412e7f98", + "id": "F05.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "Alto", "subcategory": "Plano IP", @@ -1253,6 +1379,7 @@ "category": "Topologia de rede e conectividade", "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": "F05.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "Baixo", "subcategory": "Plano IP", @@ -1264,6 +1391,7 @@ "category": "Topologia de rede e conectividade", "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": "F05.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing", "severity": "Alto", "subcategory": "Plano IP", @@ -1274,6 +1402,7 @@ { "category": "Topologia de rede e conectividade", "guid": "f348ef25-4c27-4d42-b8bb-ac7571559ab9", + "id": "F05.04", "link": "https://learn.microsoft.com/azure/site-recovery/concepts-on-premises-to-azure-networking#retain-ip-addresses", "severity": "Alto", "subcategory": "Plano IP", @@ -1284,6 +1413,7 @@ { "category": "Topologia de rede e conectividade", "guid": "153e8908-ae28-4c84-a33b-6b7808b9fe5c", + "id": "F05.05", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "Média", "subcategory": "Plano IP", @@ -1294,6 +1424,7 @@ { "category": "Topologia de rede e conectividade", "guid": "41049d40-3a92-43c3-974d-00018ac6a9e0", + "id": "F05.06", "link": "https://learn.microsoft.com/azure/dns/dns-private-resolver-overview", "severity": "Média", "subcategory": "Plano IP", @@ -1304,6 +1435,7 @@ { "category": "Topologia de rede e conectividade", "guid": "1e6a83de-5de3-42c1-a924-81607d5d1e4e", + "id": "F05.07", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-name-resolution-for-vms-and-role-instances", "severity": "Baixo", "subcategory": "Plano IP", @@ -1313,6 +1445,7 @@ { "category": "Topologia de rede e conectividade", "guid": "614658d3-558f-4d77-849b-821112df27ee", + "id": "F05.08", "link": "https://learn.microsoft.com/azure/dns/private-dns-autoregistration", "severity": "Alto", "subcategory": "Plano IP", @@ -1323,6 +1456,7 @@ { "category": "Topologia de rede e conectividade", "guid": "ee1ac551-c4d5-46cf-b035-d0a3c50d87ad", + "id": "F06.01", "link": "https://learn.microsoft.com/azure/bastion/bastion-overview", "severity": "Média", "subcategory": "Internet", @@ -1333,7 +1467,8 @@ "category": "Topologia de rede e conectividade", "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", + "id": "F06.02", + "link": "https://learn.microsoft.com/azure/bastion/bastion-faq#subnet", "severity": "Média", "subcategory": "Internet", "text": "Use o Bastião do Azure em uma sub-rede /26 ou maior.", @@ -1342,6 +1477,7 @@ { "category": "Topologia de rede e conectividade", "guid": "e6c4cfd3-e504-4547-a244-7ec66138a720", + "id": "F06.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Alto", "subcategory": "Internet", @@ -1352,6 +1488,7 @@ { "category": "Topologia de rede e conectividade", "guid": "5a4b1511-e43a-458a-ac22-99c4d7b57d0c", + "id": "F06.04", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "Média", "subcategory": "Internet", @@ -1362,6 +1499,7 @@ { "category": "Topologia de rede e conectividade", "guid": "655562f2-b3e4-4563-a4d8-739748b662d6", + "id": "F06.05", "link": "https://learn.microsoft.com/azure/firewall/", "severity": "Baixo", "subcategory": "Internet", @@ -1372,6 +1510,7 @@ { "category": "Topologia de rede e conectividade", "guid": "1d7aa9b6-4704-4489-a804-2d88e79d17b7", + "id": "F06.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/afds-overview", "severity": "Média", "subcategory": "Internet", @@ -1382,6 +1521,7 @@ { "category": "Topologia de rede e conectividade", "guid": "3b22a5a6-7e7a-48ed-9b30-e38c3f29812b", + "id": "F06.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Baixo", "subcategory": "Internet", @@ -1392,6 +1532,7 @@ { "category": "Topologia de rede e conectividade", "guid": "2363cefe-179b-4599-be0d-5973cd4cd21b", + "id": "F06.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Alto", "subcategory": "Internet", @@ -1402,6 +1543,7 @@ { "category": "Topologia de rede e conectividade", "guid": "088137f5-e6c4-4cfd-9e50-4547c2447ec6", + "id": "F06.09", "link": "https://learn.microsoft.com/azure/ddos-protection/ddos-protection-reference-architectures", "severity": "Alto", "subcategory": "Internet", @@ -1413,6 +1555,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant", "guid": "14d99880-2f88-47e8-a134-62a7d85c94af", + "id": "F06.10", "link": "https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules", "severity": "Alto", "subcategory": "Internet", @@ -1423,6 +1566,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant", "guid": "c10d51ef-f999-455d-bba0-5c90ece07447", + "id": "F06.11", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "Alto", "subcategory": "Internet", @@ -1433,6 +1577,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant", "guid": "e9c8f584-6d5e-473b-8dc5-acc9fbaab4e3", + "id": "F06.12", "link": "https://learn.microsoft.com/azure/firewall/premium-features", "severity": "Alto", "subcategory": "Internet", @@ -1443,6 +1588,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant", "guid": "b9d0dff5-bdd4-4cd8-88ed-5811610b2b2c", + "id": "F06.13", "link": "https://learn.microsoft.com/azure/firewall/premium-features#idps", "severity": "Alto", "subcategory": "Internet", @@ -1453,6 +1599,7 @@ "category": "Topologia de rede e conectividade", "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": "F06.14", "link": "https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview", "severity": "Alto", "subcategory": "Internet", @@ -1462,6 +1609,7 @@ { "category": "Topologia de rede e conectividade", "guid": "d301d6e8-72e5-42e3-911c-c58b5a4b1511", + "id": "F07.01", "link": "https://learn.microsoft.com/azure/virtual-network/vnet-integration-for-azure-services", "severity": "Alto", "subcategory": "Paas", @@ -1472,6 +1620,7 @@ { "category": "Topologia de rede e conectividade", "guid": "e43a58a9-c229-49c4-b7b5-7d0c655562f2", + "id": "F07.02", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Média", "subcategory": "Paas", @@ -1482,6 +1631,7 @@ { "category": "Topologia de rede e conectividade", "guid": "b3e4563a-4d87-4397-98b6-62d6d15f512a", + "id": "F07.03", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Média", "subcategory": "Paas", @@ -1493,6 +1643,7 @@ "category": "Topologia de rede e conectividade", "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": "F07.04", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Média", "subcategory": "Paas", @@ -1503,6 +1654,7 @@ { "category": "Topologia de rede e conectividade", "guid": "7e7a8ed4-b30e-438c-9f29-812b2363cefe", + "id": "F07.05", "link": "https://learn.microsoft.com/azure/app-service/networking-features", "severity": "Média", "subcategory": "Paas", @@ -1514,6 +1666,7 @@ "category": "Topologia de rede e conectividade", "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": "F08.01", "link": "https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size", "severity": "Alto", "subcategory": "Segmentação", @@ -1524,6 +1677,7 @@ "category": "Topologia de rede e conectividade", "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": "F08.02", "link": "https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway", "severity": "Alto", "subcategory": "Segmentação", @@ -1534,6 +1688,7 @@ "category": "Topologia de rede e conectividade", "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": "F08.03", "link": "https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags", "severity": "Média", "subcategory": "Segmentação", @@ -1543,6 +1698,7 @@ { "category": "Topologia de rede e conectividade", "guid": "c2447ec6-6138-4a72-80f1-ce16ed301d6e", + "id": "F08.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-landing-zone-network-segmentation", "severity": "Média", "subcategory": "Segmentação", @@ -1553,6 +1709,7 @@ { "category": "Topologia de rede e conectividade", "guid": "872e52e3-611c-4c58-a5a4-b1511e43a58a", + "id": "F08.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/ag/ag-overview", "severity": "Média", "subcategory": "Segmentação", @@ -1564,6 +1721,7 @@ "category": "Topologia de rede e conectividade", "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": "F08.06", "severity": "Média", "subcategory": "Segmentação", "text": "A equipe de aplicativos deve usar grupos de segurança de aplicativos nos NSGs de nível de sub-rede para ajudar a proteger VMs de várias camadas dentro da zona de aterrissagem.", @@ -1573,6 +1731,7 @@ { "category": "Topologia de rede e conectividade", "guid": "a4d87397-48b6-462d-9d15-f512a65498f6", + "id": "F08.07", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "Média", "subcategory": "Segmentação", @@ -1583,6 +1742,7 @@ { "category": "Topologia de rede e conectividade", "guid": "dfe237de-143b-416c-91d7-aa9b64704489", + "id": "F08.08", "link": "https://learn.microsoft.com/azure/virtual-network/network-security-group-how-it-works", "severity": "Média", "subcategory": "Segmentação", @@ -1593,6 +1753,7 @@ { "category": "Topologia de rede e conectividade", "guid": "412e7f98-3f63-4047-82dd-69c5b5c2622f", + "id": "F09.01", "link": "https://learn.microsoft.com/azure/virtual-wan/scenario-any-to-any", "severity": "Média", "subcategory": "Virtual WAN", @@ -1603,6 +1764,7 @@ { "category": "Topologia de rede e conectividade", "guid": "54b69bad-33aa-4d5e-ac68-e1d76667313b", + "id": "F09.02", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "Média", "subcategory": "Virtual WAN", @@ -1612,6 +1774,7 @@ { "category": "Topologia de rede e conectividade", "guid": "8ac6a9e0-1e6a-483d-b5de-32c199248160", + "id": "F09.03", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "Baixo", "subcategory": "Virtual WAN", @@ -1622,6 +1785,7 @@ "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant", "guid": "7d5d1e4e-6146-458d-9558-fd77249b8211", + "id": "F09.04", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about", "severity": "Média", "subcategory": "Virtual WAN", @@ -1632,6 +1796,7 @@ { "category": "Topologia de rede e conectividade", "guid": "6667313b-4f56-464b-9e98-4a859c773e7d", + "id": "F09.05", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "Média", "subcategory": "Virtual WAN", @@ -1641,6 +1806,7 @@ { "category": "Topologia de rede e conectividade", "guid": "261623a7-65a9-417e-8f34-8ef254c27d42", + "id": "F09.06", "link": "https://learn.microsoft.com/azure/virtual-wan/azure-monitor-insights", "severity": "Média", "subcategory": "Virtual WAN", @@ -1650,6 +1816,7 @@ { "category": "Topologia de rede e conectividade", "guid": "727c77e1-b9aa-4a37-a024-129d042422c1", + "id": "F09.07", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#is-branch-to-branch-connectivity-allowed-in-virtual-wan", "severity": "Média", "subcategory": "Virtual WAN", @@ -1659,6 +1826,7 @@ { "category": "Topologia de rede e conectividade", "guid": "d49ac006-6670-4bc9-9948-d3e0a3a94f4d", + "id": "F09.08", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing-preference", "severity": "Média", "subcategory": "Virtual WAN", @@ -1668,6 +1836,7 @@ { "category": "Topologia de rede e conectividade", "guid": "2586b854-237e-47f1-84a1-d45d4cd2310d", + "id": "F09.09", "link": "https://learn.microsoft.com/azure/virtual-wan/about-virtual-hub-routing#labels", "severity": "Média", "subcategory": "Virtual WAN", @@ -1677,6 +1846,7 @@ { "category": "Topologia de rede e conectividade", "guid": "9c75dfef-573c-461c-a698-68598595581a", + "id": "F09.10", "link": "https://learn.microsoft.com/azure/virtual-wan/virtual-wan-faq#what-is-the-recommended-hub-address-space-during-hub-creation", "severity": "Alto", "subcategory": "Virtual WAN", @@ -1686,6 +1856,7 @@ { "category": "Topologia de rede e conectividade", "guid": "2e30abab-5478-417c-81bf-bf1ad4ed1ed4", + "id": "G01.01", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-end-to-end-tls", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -1695,6 +1866,7 @@ { "category": "Topologia de rede e conectividade", "guid": "10aa45af-166f-44c4-9f36-b6d592dac2ca", + "id": "G01.02", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-http-to-https-redirection", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -1704,6 +1876,7 @@ { "category": "Topologia de rede e conectividade", "guid": "28b9ee82-b2c7-45aa-bc98-6de6f59a095d", + "id": "G01.03", "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#enable-the-waf", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -1713,6 +1886,7 @@ { "category": "Topologia de rede e conectividade", "guid": "2902d8cc-1b0c-4495-afad-624ab70f7bd6", + "id": "G01.04", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#tune-your-waf", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -1722,6 +1896,7 @@ { "category": "Topologia de rede e conectividade", "guid": "17ba124b-127d-42b6-9322-388d5b2bbcfc", + "id": "G01.05", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-prevention-mode", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -1731,6 +1906,7 @@ { "category": "Topologia de rede e conectividade", "guid": "49a98f2b-ec22-4a87-9415-6a10b00d6555", + "id": "G01.06", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-default-rule-sets", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -1740,6 +1916,7 @@ { "category": "Topologia de rede e conectividade", "guid": "147a13d4-2a2f-4824-a524-f5855b52b946", + "id": "G01.07", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#enable-bot-management-rules", "severity": "Alto", "subcategory": "Entrega de aplicativos", @@ -1749,6 +1926,7 @@ { "category": "Topologia de rede e conectividade", "guid": "d7dcdcb9-0d99-44b9-baab-ac7570ede79a", + "id": "G01.08", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-the-latest-ruleset-versions", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -1758,6 +1936,7 @@ { "category": "Topologia de rede e conectividade", "guid": "b9620385-1cde-418f-914b-a84a06982ffc", + "id": "G01.09", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#add-rate-limiting", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -1767,6 +1946,7 @@ { "category": "Topologia de rede e conectividade", "guid": "6dc36c52-0124-4ffe-9eaf-23ec1282dedb", + "id": "G01.10", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#use-a-high-threshold-for-rate-limits", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -1776,6 +1956,7 @@ { "category": "Topologia de rede e conectividade", "guid": "388a3d0e-0a43-4367-90b2-3dd2aeece5ee", + "id": "G01.11", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#geo-filter-traffic", "severity": "Baixo", "subcategory": "Entrega de aplicativos", @@ -1785,6 +1966,7 @@ { "category": "Topologia de rede e conectividade", "guid": "00acd8a9-6975-414f-8491-2be6309893b8", + "id": "G01.12", "link": "https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-best-practices#specify-the-unknown-zz-location", "severity": "Média", "subcategory": "Entrega de aplicativos", @@ -1794,7 +1976,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "e85f4226-bf06-4e35-8a8b-7aee4d2d633a", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", + "id": "H01.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/platform-automation-devops", "severity": "Alto", "subcategory": "Topologias de equipe de DevOps", "text": "Verifique se você tem uma equipe de plataforma de DevOps multifuncional para criar, gerenciar e manter sua arquitetura de zona de aterrissagem do Azure.", @@ -1803,7 +1986,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "634146bf-7085-4419-a7b5-f96d2726f6da", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "Baixo", "subcategory": "Topologias de equipe de DevOps", "text": "Objetivo de definir funções para a equipe da Plataforma de Zona de Aterrissagem do Azure.", @@ -1812,7 +1996,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "a9e65070-c59e-4112-8bf6-c11364d4a2a5", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", + "id": "H01.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-teams-topologies#design-recommendations", "severity": "Baixo", "subcategory": "Topologias de equipe de DevOps", "text": "Objetivo de definir funções para que as equipes de carga de trabalho de aplicativos sejam autossuficientes e não exijam suporte da equipe da plataforma DevOps. Consiga isso por meio do uso da função RBAC personalizada.", @@ -1821,7 +2006,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "165eb5e9-b434-448a-9e24-178632186212", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H01.04", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "Alto", "subcategory": "Topologias de equipe de DevOps", "text": "Use um pipeline de CI/CD para implantar artefatos IaC e garantir a qualidade de sua implantação e ambientes do Azure.", @@ -1830,7 +2016,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "0cadb8c7-8fa5-4fbf-8f39-d1fadb3b0460", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.05", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "Média", "subcategory": "Topologias de equipe de DevOps", "text": "Inclua testes de unidade para IaC e código de aplicativo como parte do processo de compilação.", @@ -1839,7 +2026,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "108d5099-a11d-4445-bd8b-e12a5e95412e", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", + "id": "H01.06", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle#automated-builds", "severity": "Alto", "subcategory": "Topologias de equipe de DevOps", "text": "Use segredos do Cofre de Chaves para evitar a codificação de informações confidenciais, como credenciais (máquinas virtuais, senhas de usuário), certificados ou chaves.", @@ -1848,7 +2036,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "a52e0c98-76b9-4a09-a1c9-6b2babf22ac4", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", + "id": "H01.07", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending", "severity": "Baixo", "subcategory": "Topologias de equipe de DevOps", "text": "Implemente a automação para File > New > Landing Zone para aplicativos e cargas de trabalho.", @@ -1857,7 +2046,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "cfe363b5-f579-4284-bc56-a42153e4c10b", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H02.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "Alto", "subcategory": "Ciclo de vida do desenvolvimento", "text": "Garantir que um sistema de controle de versão seja utilizado para o código-fonte das aplicações e IaC desenvolvido. A Microsoft recomenda o Git.", @@ -1866,7 +2056,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "c7245dd4-af8a-403a-8bb7-890c1a7cfa9d", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.02", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "Baixo", "subcategory": "Ciclo de vida do desenvolvimento", "text": "Siga uma estratégia de ramificação para permitir que as equipes colaborem melhor e gerenciem com eficiência o controle de versão do IaC e do código do aplicativo. Revise opções como o Github Flow.", @@ -1875,7 +2066,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "12aeea20-9165-4b3e-bdf2-6795fcd3cdbe", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", + "id": "H02.03", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/development-strategy-development-lifecycle", "severity": "Média", "subcategory": "Ciclo de vida do desenvolvimento", "text": "Adote uma estratégia de solicitação pull para ajudar a manter o controle das alterações de código mescladas em ramificações.", @@ -1884,7 +2076,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "2cdc9d99-dbcc-4ad4-97f5-e7d358bdfa73", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", + "id": "H03.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/infrastructure-as-code", "severity": "Alto", "subcategory": "Estratégia de Desenvolvimento", "text": "Aproveite a Infraestrutura Declarativa como Ferramentas de Código, como o Azure Bicep, Modelos ARM ou Terraform para criar e manter sua arquitetura de Zona de Aterrissagem do Azure. Tanto do ponto de vista da carga de trabalho da plataforma quanto do aplicativo.", @@ -1893,7 +2086,8 @@ { "category": "Automação de Plataforma e DevOps", "guid": "cc87a3bc-c572-4ad2-92ed-8cabab66160f", - "link": "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", + "id": "H04.01", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/landing-zone-security#secure", "severity": "Alto", "subcategory": "Segurança", "text": " Integre a segurança ao processo já combinado de desenvolvimento e operações em DevOps para mitigar riscos no processo de inovação.", @@ -1902,6 +2096,7 @@ { "category": "Organização de Recursos", "guid": "cacf55bc-e4e4-46be-96bc-57a5f23a269a", + "id": "I01.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming", "severity": "Alto", "subcategory": "Nomeação e marcação", @@ -1912,6 +2107,7 @@ "category": "Organização de Recursos", "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": "I02.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "Média", "subcategory": "Assinaturas", @@ -1923,6 +2119,7 @@ "category": "Organização de Recursos", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5c2622f5-4b69-4bad-93aa-d5e8c68e1d76", + "id": "I02.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", "severity": "Média", "subcategory": "Assinaturas", @@ -1933,6 +2130,7 @@ { "category": "Organização de Recursos", "guid": "667313b4-f566-44b5-b984-a859c773e7d2", + "id": "I02.03", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "Média", "subcategory": "Assinaturas", @@ -1943,6 +2141,7 @@ { "category": "Organização de Recursos", "guid": "61623a76-5a91-47e1-b348-ef254c27d42e", + "id": "I02.04", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "Média", "subcategory": "Assinaturas", @@ -1953,6 +2152,7 @@ { "category": "Organização de Recursos", "guid": "8bbac757-1559-4ab9-853e-8908ae28c84c", + "id": "I02.05", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups#management-group-recommendations", "severity": "Média", "subcategory": "Assinaturas", @@ -1964,6 +2164,7 @@ "category": "Organização de Recursos", "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": "I02.06", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group", "severity": "Média", "subcategory": "Assinaturas", @@ -1973,6 +2174,7 @@ { "category": "Organização de Recursos", "guid": "74d00018-ac6a-49e0-8e6a-83de5de32c19", + "id": "I02.07", "link": "https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---require-authorization", "severity": "Média", "subcategory": "Assinaturas", @@ -1982,6 +2184,7 @@ { "category": "Organização de Recursos", "guid": "92481607-d5d1-4e4e-9146-58d3558fd772", + "id": "I02.08", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "Média", "subcategory": "Assinaturas", @@ -1991,6 +2194,7 @@ { "category": "Organização de Recursos", "guid": "49b82111-2df2-47ee-912e-7f983f630472", + "id": "I02.09", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "Alto", "subcategory": "Assinaturas", @@ -2000,6 +2204,7 @@ { "category": "Organização de Recursos", "guid": "2dd69c5b-5c26-422f-94b6-9bad33aad5e8", + "id": "I02.10", "link": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits", "severity": "Média", "subcategory": "Assinaturas", @@ -2009,6 +2214,7 @@ { "category": "Organização de Recursos", "guid": "c68e1d76-6673-413b-9f56-64b5e984a859", + "id": "I02.11", "link": "https://learn.microsoft.com/azure/cost-management-billing/reservations/save-compute-costs-reservations", "severity": "Alto", "subcategory": "Assinaturas", @@ -2019,6 +2225,7 @@ { "category": "Organização de Recursos", "guid": "c773e7d2-6162-43a7-95a9-17e1f348ef25", + "id": "I02.12", "link": "https://learn.microsoft.com/azure/architecture/framework/scalability/design-capacity", "severity": "Alto", "subcategory": "Assinaturas", @@ -2029,6 +2236,7 @@ { "category": "Organização de Recursos", "guid": "4c27d42e-8bba-4c75-9155-9ab9153e8908", + "id": "I02.13", "link": "https://azure.microsoft.com/global-infrastructure/services/", "severity": "Média", "subcategory": "Assinaturas", @@ -2039,6 +2247,7 @@ { "category": "Organização de Recursos", "guid": "ae28c84c-33b6-4b78-88b9-fe5c41049d40", + "id": "I02.14", "link": "https://learn.microsoft.com/azure/cost-management-billing/cost-management-billing-overview", "severity": "Alto", "subcategory": "Assinaturas", @@ -2049,6 +2258,7 @@ { "category": "Organização de Recursos", "guid": "3a923c34-74d0-4001-aac6-a9e01e6a83de", + "id": "I02.15", "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", "severity": "Média", "subcategory": "Assinaturas", @@ -2060,6 +2270,7 @@ "category": "Organização de Recursos", "graph": "resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant", "guid": "5de32c19-9248-4160-9d5d-1e4e614658d3", + "id": "I02.16", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs", "severity": "Média", "subcategory": "Assinaturas", @@ -2070,6 +2281,7 @@ { "category": "Segurança", "guid": "b86ad884-08e3-4727-94b8-75ba18f20459", + "id": "J01.01", "link": "https://learn.microsoft.com/security/benchmark/azure/security-control-incident-response", "severity": "Média", "subcategory": "Controle de acesso", @@ -2079,6 +2291,7 @@ { "category": "Segurança", "guid": "01365d38-e43f-49cc-ad86-8266abca264f", + "id": "J01.02", "link": "https://www.microsoft.com/security/business/zero-trust", "severity": "Média", "subcategory": "Controle de acesso", @@ -2088,6 +2301,7 @@ { "category": "Segurança", "guid": "5017f154-e3ab-4369-9829-e7e316183687", + "id": "J02.01", "link": "https://learn.microsoft.com/azure/key-vault/general/overview", "severity": "Alto", "subcategory": "Criptografia e chaves", @@ -2098,6 +2312,7 @@ "category": "Segurança", "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": "J02.02", "link": "https://learn.microsoft.com/azure/key-vault/general/overview-throttling", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2107,6 +2322,7 @@ { "category": "Segurança", "guid": "2ba52752-6944-4008-ae7d-7e4843276d8b", + "id": "J02.03", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2116,6 +2332,7 @@ { "category": "Segurança", "guid": "dc055bcf-619e-48a1-9f98-879525d62688", + "id": "J02.04", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2125,6 +2342,7 @@ { "category": "Segurança", "guid": "6d70ba6c-97be-4995-8904-83845c986cb2", + "id": "J02.05", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2134,6 +2352,7 @@ { "category": "Segurança", "guid": "913156a1-2476-4e49-b541-acdce979377b", + "id": "J02.06", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2143,6 +2362,7 @@ { "category": "Segurança", "guid": "cdb3751a-b2ab-413a-ba6e-55d7d8a2adb1", + "id": "J02.07", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2152,6 +2372,7 @@ { "category": "Segurança", "guid": "17d6326a-f625-4ca4-9e56-95f2223ace8c", + "id": "J02.08", "link": "https://learn.microsoft.com/azure/key-vault/general/monitor-key-vault", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2161,6 +2382,7 @@ { "category": "Segurança", "guid": "b12308ca-5017-4f15-9e3a-b3693829e7e3", + "id": "J02.09", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2170,6 +2392,7 @@ { "category": "Segurança", "guid": "16183687-a047-47a2-8994-5bda43334f24", + "id": "J02.10", "link": "https://learn.microsoft.com/azure/security/fundamentals/encryption-atrest", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2179,6 +2402,7 @@ { "category": "Segurança", "guid": "91163418-2ba5-4275-8694-4008be7d7e48", + "id": "J02.11", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2188,6 +2412,7 @@ { "category": "Segurança", "guid": "25d62688-6d70-4ba6-a97b-e99519048384", + "id": "J02.12", "link": "https://learn.microsoft.com/azure/key-vault/general/best-practices", "severity": "Média", "subcategory": "Criptografia e chaves", @@ -2197,6 +2422,7 @@ { "category": "Segurança", "guid": "4e5695f2-223a-4ce8-ab12-308ca5017f15", + "id": "J03.01", "link": "https://learn.microsoft.com/azure/active-directory/reports-monitoring/overview-reports", "severity": "Média", "subcategory": "Operações", @@ -2206,6 +2432,7 @@ { "category": "Segurança", "guid": "4e3ab369-3829-4e7e-9161-83687a0477a2", + "id": "J03.02", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/logs-data-export?tabs=portal", "severity": "Média", "subcategory": "Operações", @@ -2215,15 +2442,47 @@ { "category": "Segurança", "guid": "09945bda-4333-44f2-9911-634182ba5275", - "link": "https://learn.microsoft.com/azure/security-center/", - "severity": "Média", + "id": "J03.03", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/concept-cloud-security-posture-management", + "severity": "Alto", + "subcategory": "Operações", + "text": "Habilite o Defender Cloud Security Posture Management para todas as assinaturas.", + "waf": "Segurança" + }, + { + "category": "Segurança", + "guid": "36a72a48-fffe-4c40-9747-0ab5064355ba", + "id": "J03.04", + "link": "https://learn.microsoft.com/azure/defender-for-cloud/plan-defender-for-servers-select-plan", + "severity": "Alto", + "subcategory": "Operações", + "text": "Habilite um Plano de Proteção de Carga de Trabalho do Defender Cloud para Servidores em todas as assinaturas.", + "waf": "Segurança" + }, + { + "category": "Segurança", + "guid": "77425f48-ecba-43a0-aeac-a3ac733ccc6a", + "id": "J03.05", + "link": "https://www.microsoft.com/en-gb/security/business/solutions/cloud-workload-protection", + "severity": "Alto", + "subcategory": "Operações", + "text": "Habilite os Planos de Proteção de Carga de Trabalho do Defender Cloud para Recursos do Azure em todas as assinaturas.", + "waf": "Segurança" + }, + { + "category": "Segurança", + "guid": "24d96b30-61ee-4436-a1cc-d6ef08bc574b", + "id": "J03.06", + "link": "https://learn.microsoft.com/mem/configmgr/protect/deploy-use/endpoint-protection", + "severity": "Alto", "subcategory": "Operações", - "text": "Habilite o Defender for Cloud Standard para todas as assinaturas.", + "text": "Habilite o Endpoint Protection em servidores IaaS.", "waf": "Segurança" }, { "category": "Segurança", "guid": "15833ee7-ad6c-46d3-9331-65c7acbe44ab", + "id": "J03.07", "link": "https://learn.microsoft.com/azure/security-center/", "severity": "Média", "subcategory": "Operações", @@ -2233,6 +2492,7 @@ { "category": "Segurança", "guid": "e5f8d79f-2e87-4768-924c-516775c6ea95", + "id": "J03.08", "link": "https://learn.microsoft.com/azure/azure-monitor/logs/design-logs-deployment", "severity": "Média", "subcategory": "Operações", @@ -2242,6 +2502,7 @@ { "category": "Segurança", "guid": "b03ed428-4617-4067-a787-85468b9ccf3f", + "id": "J04.01", "link": "https://learn.microsoft.com/azure/storage/common/storage-require-secure-transfer", "severity": "Alto", "subcategory": "Visão geral", @@ -2251,6 +2512,7 @@ { "category": "Segurança", "guid": "159aac9f-863f-4f48-82cf-00c28fa97a0e", + "id": "J04.02", "link": "https://learn.microsoft.com/azure/storage/blobs/data-protection-overview#recommendations-for-basic-data-protection", "severity": "Alto", "subcategory": "Visão geral", @@ -2260,16 +2522,17 @@ { "category": "Segurança", "guid": "6f704104-85c1-441f-96d3-c9819911645e", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/roles/security-planning", + "id": "J05.01", + "link": "https://learn.microsoft.com/azure/active-directory/roles/security-planning", "severity": "Alto", "subcategory": "Acesso privilegiado seguro", "text": "Separe contas de administrador privadas para tarefas administrativas do Azure.", - "training": "", "waf": "Segurança" }, { "category": "Segurança", "guid": "9a19bf39-c95d-444c-9c89-19ca1f6d5215", + "id": "J06.01", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "Média", "subcategory": "Estrutura de habilitação de serviço", @@ -2279,6 +2542,7 @@ { "category": "Segurança", "guid": "ae514b93-3d45-485e-8112-9bd7ba012f7b", + "id": "J06.02", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/service-enablement-framework", "severity": "Média", "subcategory": "Estrutura de habilitação de serviço", @@ -2289,7 +2553,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "September 07, 2023" + "timestamp": "September 14, 2023" }, "severities": [ { diff --git a/spreadsheet/macrofree/alz_checklist.en.xlsx b/spreadsheet/macrofree/alz_checklist.en.xlsx index 0caf5a0a2f800597950dd770b38da34bb35f39dc..f050c7b222f8f8667f518b7b9eb466281ce916b2 100644 GIT binary patch delta 41201 zcmY&fWmHsc*A{7zZlt@rQ%YJIq@}yN=Fr_;(w)*JAf3{k(nxp5H~RSg_(OC(g8P;G+8lGXs7&2V{H&$ASk%#99Z~aesN|0F-;WpR$7hq(Zz$gFZs}a4_2$-502g zvGGuoyE_{cq)MWho^b|}SoL-Eas_q@nU2k^y+mIc%s$(T> zqP7=^|A$xIEyNEPls||~%m)O5a^Jk6e1J@dDaB1#gM$TZ61KSFnI1H7w|JV4LqFoI z>)(tWiMN&8Tt_Z#I(P`wJnq0q`K#&3<^?CV>b_jV!lPoAilTGOrZ3iU8@jC&O8Umf zW{JObkG&rlce#{(>|L0AaA{g?0v>v%&)x5u+S<4PL;j_XQWWd)xLRA+tHD=mqSGa@ z9&=Ls<3_-($|l5(U+ehw>=eMPE{sZ=hko=sS;&4ldsEFrP^K_o(_ltmtY{mkh4&KZ+=<@u2qA#B*Uzf_jdtapcAOPY)5L47 zugRW`^h=?)PdYW@$G_IqA60>uj?!?>SLYY^8)Be>{3p>u@{Xi>Xv||}l^Y80s-u&U z*V!J**{JqC**g{W`OXh1#0dMrK=3}4T<()__5y$7&MD~docbYzW9+eK(cPT)sfq1^ zpSAXhm3^t!?fT|a&B1$<_yM;33#Fh<%-($bO9S!YIQ?9d#vK(Zal-tv`cw6_X2
(Y+O6=|`%fT6er?vJJ~5#Vd!-7s9#7lv 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 delta 41091 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�ZIDM4(55VU=r1^}AM~7!e{Nmi8>&?1sb?=0 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 o3Lz7QxQ6Z@*HE{_NFaW=CMUVs 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�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 diff --git a/spreadsheet/macrofree/alz_checklist.ko.xlsx b/spreadsheet/macrofree/alz_checklist.ko.xlsx index 24f1b8676b363a710b392e9279478c07c2443747..22a9884352470bf0acb24138cd70ffc0af6f7b77 100644 GIT binary patch delta 47291 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

?(%s_9}+N}&70va?nrTeo%Sw* zv5n_)-5qz_>=$t`2Gwb9gEtte3Ge%YTcFc2Uf;2IKo%L$o9DOKt>sJKQc?|5?~|=f zN0%PLBG0|Ba9KXbqF@N|eh^ZoQS=^-B(<;uPVssg!~R(sAqdL%R=?W*oMtHnD7n}_ zFKy;e41_B>LWV1L;~Y$Zfg<|*p=t1S3G&xw>98GxM<(u!xA3qn7lf`N=kU(&|CF(t zG3U!a^kkR#ZfEg5jSFh>x>_9f_4TxIjaSXEux)w#%7%^Qb^0W5m}3Z; zQbI1u-Fx>+DxS(N??o)$j@s4|z@)hF*Rt)`jdQmcUlD z0ZXnbEVj{^c0txj<^G*=ks~QAk8HI>9@^A`+>7@F{%`&c4+$GHLkko02a&<;My~S? ztz>E8x~gL&bJNTANgiV2FkSGacz7-z3ggYW-+hi9CT@gKKcdYr1BTUI8x-L^wweoS zd!Kszbm2h5saEvs*mT=En;_6mIRljs+t3@DginuFu|H&pg0P|DR>RpZ(RhOU3%w-0q(1UgH<-sfm*HGGw9kbd!8e^O;HIGFhH0`=H&$Vi7*jGqLv3ppHi*75ZaBFYJZBZG#G z17|NM^X!}6{FP&YV?N%Nnt@Foua)=G>Zf{UMS0l_tF}NzCuKkn14(W|Y3mX^p4kco z_fc+D3PFeKLPky@i2VNQk4n2j*(bEVSUMp9uHh2=ZRtw_F_w+7dYND(u#1gsi?kwfo@O+RiA!)-BjUuPc!80*0qZY zLIXMZ`E&1Mj-}QR(aP_HA@6p(R@MUd*^kk1pY{beaK^`$Csy~QgrW#NU+*BmcM5$yq zCwvp+dv9_4o#+gKo9W9}|Ir5#>A?TlV@L&}pQkMo5AwTvD*1P!W_o>wm$&e{&!k=IRl@sykPP@P-3VEx3=5?$h;hAM;-CYGd9%{0w%4vC47le;S4 z(HgSsIEz94Mjk*r>?H)6T5yJzO7Q(U-VnR&#|Z=#**7vgDwOGX3yAlT*;=8O4bUi%|%%1|vYau9EtPlQ3cxYMk<) zK0XJsB_t%E#U=<&!-UZ(#h3@xm6K^=d>l25FsFl40Yqw^S&}-%2e0y^vba#FsXqJ* zh!c`Rd2u&zd2#On@gU!?kSshrN+i&d%WN=tNE6{yqV)!M$(xXBQ$U;PuwuG~tY2|t zQ@u(6@|FM;dt(ZlW8UqZM$C@g5_FiVr9l6C zh>A)LS|(DK2qqRG?3L1@jeO0V)6{|8cGVM%`rpJvDa?$<`+aEq9!jO7fTE7i*Za)L z)yLva^wA@|H!p5ubvm&prl^gD!p>2JJVX?CAM_-7%A zjxGqhIf(>}Zm9pZpWngglpzOz3H?V-yfE<5tmhq}%0c{jxy(c;I4C8BPaq^;=SXpi z8*CB6=_Ym~=w#!b>jaH+@tl-CP~rR=hLE)o3h=*y3jlq?Nm2NsARjLoUXF_0!01wR z#|){{LEt*!?OesEzJDuVB0!nah!G!?0zF{haFS~4H= z(bc{g=cYPM0=Zyd|M~re=b=ChlxH}&Fh8d91+AUu5H)_8wVv9=&gm%mD!lC%n+^f~ z{fy-)j|U;&Iz*6u2g8TG1)` z*#XS=LZNR>^LDlEk$D4h%**14EH=_8EhkkKNF3z-Fs;lUUcR=ENK&01m6_h-W3clr zo;VTi9?)P6qsj!*Y1F|ciokTxUnrc#jn^eqynOnZTqKKTxb+7h_S6!j#L${w9 zcF?J-70gZtr#{NAdGvg{U3o$PL?!GAykX4{Cfe15Ec%tu>cR7NkhfK!@h?|`g^Y%! zoB6}s!xmeD(FUW>#d4V(kj0dr z`&=LxOR`?IFDJz?d4LH9i9y8YnoCf=i91Q|8&^G$!=RrHO z^#-Le#06X_^@>LQOd|!~+UX2s5_i`m@$_ro=llNp#g$JZM<;DJ7CZmGP~> zRb;u<@h{0$W0ha2s2Hv{QOhD`k8|O5cf4&>*#z6uhr~LsqI$t#mTlC_t?V(N>SQ^54OglhpK0LC*Y4O$pfD!0ttC-Q88MY(n4PE8D$@u~9)> zKQ2xeMUrC&neFCEg?gVTJd*^MAFGuZqY{#-bVeOetq`uIF0HMPcE?1G=cd(k{Dg@A zj|$;I6!>4yYL28-`wMJ7c(Y$bE;GPlwY8_eP;V9!zjf+Ow0pWQ{ely(6F3mRqy~sw zKP%g{lB>>7FTKK>g3j)#B2XLMT?My2|Naq-Go&t03*e1umb=Z$)Uz%ff}l@>+eQMo zjs6a1=wrVO*?y?YJ|r_R?IK`- zCJeo#@cW6{rt|&>x|kSk3}=NH|M+!6IV`O`{e4bomLVbI9=^1lJfM73MVCBrPK4U> z8UZt)sF*=hl;*H(H{9twH85@GU!ovMM&*?Glo0cR?wr?vzH}01+IYTEV5&8;A-4}J zfn#O^6}c`nC&`!H^X2Hlp=*`U?7e8*VH7;O=c0Vr)vTnl3y&%3^jhoAalA?6vCniE z;^E=w^|^fO6mEFTU0uEfwzuUn}z5=r%BmV9*qP}hYe-vFcxW6fJ;V| zSXO);agN`wd=`?T_uAvQ4To5y+0*y*=|(>@o69I%4E%%T!`lYWR@w*qn0ih|LS!(T z{5A%G#PJo0fDG%b5XvA6Jk^hf-G^v}y=f6sJu2P+QsH*saKMw&<##IiTB%%CrH*SQ zVa3Wz`@(IfPnbmiOZ}hkM!cbz-u4-S~!Z;yxXQLG8?PL)?c^q zR`m%H%Yqws*;v%PJFEtuO;d+G^J2288+PfPKZQG_Ik9U#Ms$jul-BV)EvZ%$!4v|s z(Aok5R_m-;gztrZM!6!u($R1+(xeFx_|;J)o!y!09k8I~{7kGs`<)Q!>s2iV-gNyB zr48TCY5t0dbSS%=!nY5m zL#iY%U)G$*T;pk|p#B#Kd=2{<*=R7@nDTf167*^6w5o|YvT-jD4Bjl7}uZd zMleOuG|omarGY8?n*NOn8%I%BKe1q@MOjq?7gbfUg(a2cQy}iYE3|iv#BwQK5y;Vs9)co&1+)L6PHgT5Qw# z5Lfu87^bpa-IW@9tviy&2KpS{mW(yJILqJYfs{a(x^W&}EUhh-938_Y@{Qyc6{Hmi zmIg#H%hjWJQ8szhtuhT9FJF5i(J|1>B_TH&Ei*|`E*-_jZ+J|k8Pw%HTwssxrN|CC$;;>2C*kpatKYeywNeur#qP{V_ zuD|KJjnmk+?Z!^pIE`)F#%XNZw(X>`(bz^~8+}jm@BO@=@*(@W&g_}B*3A4c`}Yv? zFr`QSVb{y)+|*iz40yMUg+Pb*jF|W_c$>b(4libg^@>w@q4>AWFw+j0tCLiX(bug5$A?}(OQO*lYXyPETERfQQbJsnHA}+MA^(2KDeJZ0 z2(2*%U{;zT)`EB2MQfuA)J4^ zte#k;^}`?{xH_>6uN4Fno05~d(+IOWurvgB4Ovo!{L*oN%GqJYu5p}*^93_!`PXbZ zQPV?Yn)D5N7AibV%Y=%76|{{t?gjPfPEF7#hg!bV_z@LK_gJ5!oS%@Bz`+4Z2*3k* zbzyVDNf(FUkX`Ar!1cvoTIMK4@q9J3BGFJWAEjH$#5`Iws*#prQ$b?E)eH-kAEp1> z@{$GkE;JRkD!o@G#4wIvLRsW6i5TXxC%8PgoXre1Kv$e5ST}VyW{01>DId z@#MQzN@B9S`nh%sA*-WAMqw)@;tB3;{{Hn?5se9{;m(I!AeSPpze$3iUC+k ziXJ!jX1Sf4f09txitj;U0t5;D#3NYncK{%Iv4|p)a(TouEQ-~%Wg?0-v`)s2OFQZ! za7P^i@AnIH;io-}yv?RC$jrOMPGEEIVDFN=v=@%;?;PT~-2y3AP->UH&ztpYHS4yc ztZ9)TUka}Mg3(-M-1zF+jbJ_~gpZij&f8Yv4BW~E#ucxvPq1TiGwB+iQVui*Ai5t@ zoPb70gNs4A&7-{6VG$pa9}lalB2q2J2U!w#FA#$Lulieui7hsol+4{{KfqnT&RR*{ zkYfL=fW15~$Kxhx_2>HYYmwF=ErpkAN8QuDWuA=X_0hHWZ4hf#Vxx~q^cHe15k*4LU?b?!2^^9{FkmWbrD+%4Ro zbF&%_YLm|p@pbTum>>)>$9GO6tlV7rIcVF6T@95vQ7VG{Au3wHgn%8+zZaZ`M{WYX z;OhGe&Uap{lG8jTy>U^+d15wuB)k~Qn#=GvNJ9P|W>4?qqERp@b98zgKk|W0vCFmYfLW-S=JMF1CO7B zq-lQQ;pM{h_6f}%+BMp|*+&5Dj3@!*Kete)76p|y<-W4w; z4JHdoS0JDi1p9Y5;1*mQvF?CO@Foq|%*`HPos@N-OfNpoQIh0gn7Y($up;vA$>Ck& z51Qxa8Dd~|5}qQ@(g&`}+Gy?-F8^ndGg4&P?A+Fwf_7fv0GPZe`Hz(sDWwxmp$;6Y zFj_byN?x!SAhPiHK@>7CVbMq>qCGYB)h-9wjDpvH z55Vf-lr2Qs2Y{4M5yc2J&15*Y+-TA8Y3(hRV@*~J8r6c6<00c2q=9F&{mlv^mP+E+ z_oVQ`*W^~&2XoS@k)fOo$aE`TnL0XCSP=V#y(XHb1B$Q1-?gp?c!5geXP>GVabrUs ze9@*Cbh&?Y4{JQykbX>`;8$RMcDrx>-uC+Ry1W$ZY*;W}m#v8uh>i!A7=+khI79kf zPQ+X!ESW?*$sSycrgD~tj6Qvj=o{z?4~zu5p6Q}%@@%3xQ9!~SYfM9OpV_!8bzphA=!RHGDD*3!v#f5n6lo>H^YtprK)tzK$axbOR zfjSd9!S5LJg`GbsMw-%QVeKW4Knr9cTETCXj)k=?!JY`O#xMOs^M@I-WeG$SRxGO2 zwJq7RVyKViYBNip5^Tl^q{$fBk$f}kTUnfth$tT*_^rD+f9+&Hgdn`uM+Vcd_jD5U7@aoR%mhxDJ z%6I|h{Yz4)V<(JK>OW1aBpKN1WhdPCy`hQ+uT60?F={tw3r0cl+G01Af-$WtAJU6)y`KeX~TsyzJ(RoVkLEnc%slO9#Jv@3 ze$NSq4wP4(C9Mb(LY)v=$@8&t2NjiJthW~;afg}aWYh6bzHyc=h;ylT>1uxp+tY-@ z0W{T@9V<(j|EaL4GAzAee-z!J|8aCW?RMKh2U@qWLPj<)R@FXlj}XoJ-JxRmxAyn%{t zQ~WB3$cCE9cRUN{4~WFd{$S-(>Qj?Apc0^0$w}?9QX!A)1?D~)5nhc2rwGzLmFt&X zH!_X8fF}Jz2u5k8bwVy?Tf*H+Q`?F&Ou3|vcG*-n?Y96MB5XzaRPb+KFv0PKOtd^L z1>{{kx^k~Dt)h|2m)o04x=m^|3~h4{3pN<(IDz#<{Nwzmzrs(Y;b*?mekxNq05-qX zSO{QjeXRGEQXr@Y$GcZVj10rZ1GD*{-ih|);xsTKHLa7N?`taU5O3EKy+<{0Wrh(; zm9h5qJLrlfl)1m|JJBpLNm0y!L|eQ_6(Tw}jpI%FYEW6m#U4@{Lx~so3*sgBo^E>x z)!lE=n%Tc<-lb_S9VsvaAfu-;QptIwd+oM7Ypy8~ZERK-eHz=Ez^siy!1{Y!Zl6u2 zx}pF(R~_+VuM^J zdTedJJFmRJPv3pqh9X>x{De^2=Ik{?Ccg%42p8 zUJsj>1C=U-T-;c|A6I+dXXI4vvW(EK1o0)K9Sxh7G8WwKuhc(N9EFZ0+I9+&wWH3h4XRlwGjP1yLtESabH8Xxu=J zU*ii008J8IkcG-E?x|f^yr^GUAlqTz=t|S5JwHhQGey+H{u)AT+ z)hS<8tDVM?iJ8vacNW^*j6VzGglJe%ES8T=P%0KIaMcMDPi7ZB5_{>pS09X3eF;t- zsA~!>OhaMl;Dt+$9h#M5I%I>8XV%8Zo&u0wyYQkz&QnxD=Q8p6*_*t+tV}=uQ<+Qw zo9U-@&zh*5luRi);a7JemLA&8(9BGhaCU2oP%~-onayl1VpYDk-BNLNrc3k%B^ajb zn+SplyyenPihd4j-qXpg4iUPww1&|i6GjPEoD}_E1Lrh8pNDJ+M%k3DgS;z&Gr-D) zj4kZ7*V_wG%qlZWLhgj2d$OwDMGgi^zvYBIU2-9VkgN!<^< zgSLn(WQ}XH(;hADMjfKJgmbsg#ZREM2zC9_uw=bKn)CCC4|tSJ>I?oIu2-4a{9{iRidefFaRsFr+G{}{qiR7Y{Ywxy&GAdrCIjL(z) z?%4cC?QiwBW)nnJFi4>=c;5+%3hF}wJzx9SA9Hy`LMfCEq?8z<{ibRKXP9xk)x3Vc zh&d3|Idgu)B9r@uWu-t(*i1SZNB`{Q80Pj5j7Z8LODQ`KZ-UO4Klobld($jGi%3e; z+RZIZT@hBH4$i_=$Ho5_7l3vF+yYsD#KlODSN6NggmE3s&8s;?3t3wCRnvq1qXuG{ z(*57g74Na%kSaR6O(ZnszglY6M9r~@;pMNPmch_@k|LRiuP#NduFMhS(+Tq*4pTDBHGASjNCejihY8=9r24`K?cO@WLokP}Fbw%&( zVL=2YaYs7|B0yG7Ddi8jE8O462SE3RFsCcX@7X25xHR}Cm^dYF#QUC^{}E zRP8=da*QfiqncIe}ZGi(|!IKddlpa{wI0 zpEo{R8BT;}2j=TOSeQrItPo-e7p>op@1K6zJ1{g^j7sFCc+hG5S@73t&iMnvOg7dx z_kzra{5tWE=oND8NIXzAD%urG5i3?Pj$RHoa&N^Y0KZbFH87<3xEJm1v*GP+X)Z1C zC-07gw+BA{v%6)C?>jS}?v8ZR>zFG^PemFbhg?9GYp0gWgA5(I=igTr%B0;U z$qmGj12QcH*n1&3F0QBl>meoN^Xr|aiA?K7J>2b~)5~Pr>65EW+3LPY+z-)Ta?iMN za+laW(g>;D2Q0l$3{G1iIRS-zk>tztfQjf=&Q4C+dzj|w&pe(QfEEJNw^e~8e_b5< zHk+*Iw%fbx_3mD+EUzhV+uAuy&(A$+^NK?FVzsZNIx=a6&NZu=UnHRgKT>L(4O1m^ zdJZ#vK0rqqdfRRskuM%o`mz^su{GRt(;bh6} zxw^MUU8fEK!e6)51OOPWJG9sRM$p<_z%z$|EI{q?_B7i%F$g@2u>KF>A7W8rIwlOV z5z-o>M_j!=aipA7iAA@^uy+extgD&{aXj%et)$pto-QPe)tF8lv;>ibii0LW`m*Ko7r9Pki$t@Bc0Inrlwdbanx`K}Qj{|4Z&9?4 zc8PmgOa`mxo+jYI%PD{b2uj&O3%ncxT+=&UKWFRG^?uUzH zm_{w;O9>`&)FYaEQ`{v;y+<_vkXOtkX@-$*23&r*XS=01Jfd9^kzIb6@Q<^i^evtW2KvzPr9H2_d{aCBFakL0v2sPMN0!|;!g+bILR zm%cAU?;nt(QTMg5Jcs5iZIAOHM18mmCTp6oI;(oG@Gv7g+oSpkf9Gd-4BUJ5PSEnU z4-^G1aKs_l`yh#ng%sbkAj;N()X=gRWvwoS-2G}i|8#uzk&QZqlh5G!S=KT(0GWsz zM4S1|auKFvkj93ndge>AZwyS*{7&B`nbmoQm+0_n<%^6h{w&x_olTTA8dAvyDuv&u zpRWO4+4>&;m?vu&M>xwaRwFWO@_}6(SOvI#1k>%UeY1ICTUK@ZJ(+`8?EJ3nu|p!7 zFz_{1XHg_26E)I8>LwmB1$?=npuGgmA^YfK_9x44f#S~K0_j4;1uJ>UNZSwe7y#0T4TpH_%cFlb7ZO&k zTShiv;gu+Bib4-mh+V2Rs)JcZus{KT6z4&#?<{=aO<*DJ)zH(FG$vAZk+m4PZ-x(H84V=ae{C~m`vrmo zQyDanC)^vp9Z-Rd$O^3G(;iZt-X?otj^oBF$Jnj4{m}rJ$}c{^3jP-x8=8Hpj6JDD zPrht2RQwDkiL#O%c3gfj^1U)yAR6F5Mq*#;CvPM0v-D?eWFl(AV)pH4$$^qpHCDmw zvk8nMTGbJ^h>@b)pS*J|Q zcuIbW->Vm>@uUGKYCp3xF4FUGmQ+}ey7)wsr@DsFYFO|zIyP}a4l2ig7#BbKgfF4Pqoc|rBCG^chi|Y zT^2#Y)^;XZw!-13!E%G!X^WgjUs=U@iLp zRX3?<_5&5*XJD&_6GYfK;xJ zDy^jRy86_8?f8o8@48jOQ-%AgatrB7VPWK3XxdiJ48POO4)F5loP1C8i@V3_c`7wu zA)%2;Qre0h65e|OQ-1g3GTx9%wEYK{u4V}@gEGnC`fi9LnQKOK8LzIY$p1*x6cq9Y zm^OaDqr`cVZ~Q3!JIE}VYoWQ0#)McY$^MzuuP3aB9{;qI&k)iSX@$1?J?$5XU z9e-6C0=L&X=e2Dy0Vf4I+Ey4h_}3M!CbYG8g5PK~e$74vB=c%&~RMG1qNv?p*&z8$fMIqCeH!5R1YK(4_3;pMp=W-z7O|!_?Qa z3pugb3mYZ9LtCWF4k8&%P0BN@P`K_6Gz+xWGUS@L#i~|Y5BD)Y>s@{}i*o3HskkLq zh_Z&S2=*NLdoaaYuUsutMK*zApQ@LeHpep5O0#U17^Px79_p%z!#}_OT~ov23&0`O zQ-9(#9MvswzGfEAs){hVDd{lRY1xvkQ0psyh|`yB0F$7ukIAp&a~-MZl`lMk@2kFv zzv|AbiX?4u&wlcWxOmj49rU|{-p+zn4Pzv~K$RbYeN+^&-|elsTLjFM`-2NbLu)|{ z;_Ge6Uq9jcTxgSD{0_dtT3_0t! z>!L@X+z96VAr93Jq2v3itAzaylvZc(5U?#WL5a*j({LD4KnJ0(gj^WM_?H41hdP3C ziT|a7*B(W)-IS7PAo8nq1ge^Hboeg(AtPejT(88IPV$IcW}kN%s-i#ZXVs0HE+7WQ ztc3Ooyt@WH&uh_3NSc9orq$p_xE4x!+C(-$KOj_BmbB$HC4`#}Ae0D-_dv+GDlM@|0bFz7}6 zZS*#23mZl{K}CDBO&ng?7<~2dQ*2uWGt9e~Tf}INvX01=xp*j6AUpymVVE*VC_%ik zJk|4gS9_H5o-7bt=S`u_YR3}*uExJvZiIm@&;7Zadhm=&+fkQKdhNCEU?9jbkKF`+ zMb3vV8x?pjw<8$mAfsa!i9-zzLGAHLV&|nu$&|imu$%Q90Y&;_-Cm4EO6yx@O6wS~ z;4yQDaJx0W+s_b{e2O=Xtv2I0vjL6@%$3GVcUH1!Ob?_Q(Jht(n6$t#6s%=>iVe+- zecmwMNbcztZOR~Jx>2)ZHYEg5KOL>#v!H~f9SowK=k~Ei_)S3Z_%ydk_RTZvMB51J zj%y6jY_EZlHqEtvg#Q@Z^;qKS`sv}3zN!>>`YUfyxp;Z);P^Bw>VEvhfq|-hB%$t< zK2ApW5C@0{093rcVuL4c9yS>#S+FsuAePJ*k=*h~TXAB|@7B|S1vdZETa0t^O#~0i zVcKM7Q`vmc?2>wnXZu?FDb`?yi!RRd?6$oEe4f=-9er1YQR$tglu~v0Vc8s;34xKm zEOFY@sMj1d#9cuB67A;FW!;ihfa6Ce_X}XWXMC@k)4tr$F#k-K)iG2y*^28y1poaI z{a~+V3CuhckJ85dl@Optb$~)m1FD_6`DPiYEVnTrhV902MxX)V>_9Zywp+pb>ilPWVV$F3gRSy{#+YtHx$w0-+}IblRs5Zq{c2-fpPS(m zy8>1%Y|i!VH6C%^6Xj&`ab{&^Tkx^&7VZblQu7mOkXwj_o2k^&6JYns`zX7cjqAk} z4_Mh3x_dbP*P8+8r8vH4rr1uH$TBWu;190dK4=a`=&j~E96DBo;Wo(;BblgDSO`+{ zW?)E)>C^3la%+07t-^8MotwDW>5C($mTEDip(n1kMj%i1RVYlvOAA=&f>?|T;d6F* zxM@^i{b!wh7QJ*^u)W@YB9N~cdw_<5n*fag2p&)httAyl3K18yC|pivV&Cg2W&LLz zCA(At5YE)&K;!lx9EGlTd!5hLMLgyVn>rtFcU@ZNZw|^wzOR??1I#3X)Y42!9r#zM z5q^?aCS(CwpKHm!B0^G5bvg{u9 z86qFuxwAz-Te9(rP8hL^e!mLMSb)s(m>p4d9QlhWkD5{Owz8aD@dA&RBT^-d=snemvP!B(`&CG*I!? z>CAahWmJDMc_<;)U@wqY^+UaodZbENSM~$@2tvHN6~fV9X?$hL%qw!DJ$is=W1nhb=cpyGrhcisC@I#td8gA6^xdrmIeEPd^l`3@u}9{(Gv`0O zscQ|ytbsL$DUgz48xgAkjwt&xrKJS_hSs;#Nh=y`@^Y)*9G)(nNLs`h{hHZbo5^iT zp!_H>EMF(HxOTMKAx48>!CHMkX6NW95C(5Ee~aCu+_pn5Kr7Q1T!Uje^|8|S+Y=^y z-*?i6i9`5pLQZhCgfeE4X~$J$j+vOwio7uUJucY%mGclF0SR&Y>>;$&bL||mEKNVX zz~ne(UR9PAo^gZ|Yd6sq#1K#@dy31VF9h9}KVUxCkYjc$dWfdc0vQ<5MjSGq;3R^f zSO8JRe9qYiLsKGz?_vX+w5}}vf%^dMQaiYWv}AsK7mrJCuV}skV)Z8AFuJ|j8I|jO z=4MJI^ab8(V(_cCHeTY9=&1I|1CY>lc(fPN-^&> z4FU&7?b}W2(nbBH;x7(j{}~Orrzfiw_Zh8}U74kEO|xueGYkEDd;c_!vJ5!Sr_Yk- zE7V0FIQ=;rdUu!hH&fm2@2uMPHULdkNyMv^80mn_fQj0yA5nS)8x2XXIMiOgws@N= z+EqkP35bc0rH^*xLTcdeEA2KN;A&rHr6Z|c88R-Oz*F>IWF4Ar7MJ4_;kK6GUzTY@7Ii(%5aH zlsGE%OR#%4HroFLh)^m|C@bY#zs)2kDk7=kqg@Ba`@MPG4UnTDQ@;dz?A%v)V4Sg_%&M-QU=YMs@6u@>~w$4Y1c?2TKkk5nl_X+Y3gaB)>=+F4& z`4SCrH&QxefjpeDdx*Q`=fjW-DKm*&)>=!zs0^y<9h44r^isnuqtpM8Mps4{=_HrhkE3)juQ#$qCNiViUY;5xlM8pB1AP<+ZM?iy z=UljuXhc)ug(XVg3NS=-fOF@IT$1kqWSi%*Pke9@lhMiFG9#5`d|uZF%8lA z51c~x)ZxQsx-qa+D#3&JQKn$DizGY8#u`R86Cz%=`^;&e#>v1E3XBwMVh#Q0NDYie zB;@A>1zM@u%EhF2QiSt}%Nu>CK!gL3rnS?p&CC8olvJGTa31s@P9=|9C)vpYcxTO4l zPstiR#vSrHOjY(1%ej1w=X7KUDHE2cc5ubEXxGGd^nmJV#%ADnN%=XjbC@JiPrqwM z``dR)Q^?kYy3m3}6~bQ$nxtF?fJv1{PNLP1rEE)Xip(Nw5Q6THj!7LJJuqX9T=6GD zydG$7P!U~(oriau+p26~+V~ygeAnNL9r3yack09|2UqhTdl)X<)b2vU5Cv|jpbW~4 z1~@u+N09H2dj72{>btcMK4XL|yMIYkq@qvNa6{4b;1P2CD!40&Vc`J)@@x#-KS_sjrKb{l?t6zCdf zXv-M&X-9J6HXX15gTW!uEDrhUqdaw_u`&8w+%=r&0WCb2&S9>aa+tVpQUZC^kD#wz z0mC}f4_sNpHOnwU4$$3}5K4&E>XiOy!bEcOUrDQkq8yDtRp&nOGh#r7RRf=SCyD9M zZcW-Ujkke0!?WvzuKoQ0eVr`XlL04N=^t(?o*kFJ=uvcgL4wajd%H3boXyu#k~or=n)5$1 zE(Q~}KRk>L89fU4IyRww-ZsKJeX~|O3vZm+Kh5zj59~F07%^N$`h@ zA;+7=^*iAwNU}`oo8bcfF|N*fy7?hOeCM5UCZ`c_q1~8y2)lRSJX|bBm-52UWT#gE zw|!hLoNh*r9q{EO%&-kj>za&j1880U8NoVDrsw(QNp1Tq1K%%#r}~PnF>BLs&Q`NQ zKg?WYZI3z#S5i7n63^P+Xx$Ot=`cR)GiQUS4$v)T6vB3DF4@>-FZ8a9I>0@uW``)* zvGk30-G59yWR8Cb`%+0vtQw(@??@HdJuAYjk1-!5!f`?rbqbSLtY6;l;3jc$!cut! z4-X{tMxx;lo5(SxE&X^Hn`O#O;kL@)sAL?sXV7*h(V5+~VY#-Vd zV%}5Gl%9xnmfEJ>xFuYCj@443WLRtf-eYI%{xDxj5G`4FAqWnE6V#%UP!W?Tf@PIe z=Mrbeb7{~4-b5Aq`LS~i!I@iX+Y76PjpearQh??08R1@^eZUsP)BHBrUm{Q>4%QV5 zV4Jd4`sY}{yC*@?FqSt9qX0j!oq((f**RqlNm`mm_AquGUan*0dy4`rk42$cxuCro zv~wz+iXYf}#z;QA%}k4P6F=X*kSY%Y7p@UyR1CZkP4}Q0u45#Ui+;+dO=24s2L7pQ zykoX43{K(Vx_A zN*#dnxBCf}nxo%sTd@`mR&S7kJpo;rM5woKMJss@a6gtA2Czw!8Vn8qhjwgYwht_y zJIG~c2!@XAHux+hQ|{^~564(oe_pRAl_n@>WzC-+++8BN&SZS5lb`zAvch9?d^fo^ zIDY&-qK$=Og0*ulVI7|EpO^n1y83nSDhy># z&Pfn<3TGcrE;%?$eBw!o*Or1g83i?JQ8;fA9LD`6Xb5U~B*MJn8rRKE#(NzKFl3l$ z+{ENw8UxMG$nRk8x~18%--;>DoUU)1>m}h_{MFIFb_e4yicaq8rVEYizmE*?)tJ#6 zC4C|bNu?!|ORhVOr6!Up*m$^%<*P1u-18w5`|l-slfG}03regfgAMa#N^0Z7t8f-e zOgltzzP>X0ETFAV@xep#bJwm8olMx&&J^CHC?V1<+Z8>as=k;?=O2GgqcUe$Y2r zZtM1qJPjHe{Thmr2e3ceN4&4s`a(G>8S5tZE0`@0!fhRqd<-L2mZXSWbqq8IJn#!i zzFlcrGKHIgKK`>S{kGz>Qm1GSsPF4@7JyOij*&I3f3OUK2EKQm276a8*A?~^QTv-+%A9{;^&@wS-vDlt4TDi2Ela3iKlLXD%&Oqp1r#8BU; zn-3ea4JQf8BnN8`(ToG1;Ql|tP`Sji7p~f2MllH&r&wl$8kfj@p{S5oqanI@Y{@K6 zL0nXw%?Pai)widtCYuy%2TuM0?9gBSf2Za|AFd8*%)XvRdbA*WSgr)d`-4FrN>Tu# z*N#+XuG-`BzSe-xXOVWBH9{2wa30+xOG&f6ZQ=$=ZDs;py*p_Yp6o~E>)uG2hD5QA4(<}L5M;kDd2ItSL!pW|TuO0@5O)S73e93{6B zmRHgi%dIUDPjrP2c_Fmyp`>)!DAyOS4h8>LKM}H{NnQ;o(!v9FIQ@RoMqE-(KCk2Q z9X^EMzJ(dZh`@E5UUc`cL2YSevl`|}2G#VDUl z^xI0cRiO@hR7EZ1&96IuTPqz7t%GxJJlK|?$>-j)xRjgfQpoodh{r4oDXh9gZr)w+ zdAPkm_Gn&K9sh?ZIdA!q&wq`9*rfDaTsxCeRIlp5>e`9r+Kt}%j@N=or#lY}bf-YM`FP@9;p4}Yl zyT@N;sF1dtx_TNrQ&ekg-;K!;A5lg83ezp43gxUgh()!-Oss|aHOiS4g$5nCF$_$_ zP-cBc7xLf5x zmt~4Af9|kA?L|G9&A9Wl>-d%0v~yN0Adp97!dSo+n974*H|CuVSN z{N3TZ1Qllpu0QgAlg(EO0EJp4i8JikSZ<^I3wFr#0ErRuU_Q*t{w2W6xV3K?4T_HO zJ&Dt=)zb{)%v5rOAHcTOvkvT82W`DZZPI(tL3EP2a%9E$+Avu&IfZa||7P*}zD5t4 zhLknflwRZZ47ljufMlatnin%e3$)AOFF|}*^c>+>&B4-j(LNuSUGBjnXx7V)2f7i}X z_ZQu*D#Tle+2m6kqffI!Z3kg`GVI*(^jHhmQ*Q?CwN8WlC@yW^B`&T~5dj&HW`<<} zJihVHp}_j|Rx`6{_QC=?%t=O}=X3s59IB;?oXpP#G4k?s&h*sZw~wQQwt5kmW#dqN zPyu~BQSr72?ez$rCw0qI6)r17n&(TRp)M689N#5vVbr8en#Ua#d%V;h+u}K!tyb#uaxR z9#1=@FuE7qqcm6L3j{nM(1R~ZG$Bh|%_{TWn7OwVMwynAypfuYRs^5s{L*L`LZK=O*gK*8TS9QUBGh9a ztpL31KCcc$}Z3fWX}K?6k4orUOlVPPvsdA^Asmr8ZO`IjRw<7H^1{nB^7Rt zI?wzh2`=D*zupp1-;r)i_8`aBT@{i6(RpilRKE~B{EL~ z`CRZjcDtC8!st=mgK8)x$x9cxjax&&o-iPH3Ui(7lFidgNcv6S_1guG&JH z_i5<;aHZ%NNY}!^pXNR|e{Q+NznRS}^{3?_W(25e2*P99(x z@`hdJDVdYq$|k0?R&Tzuy*nN5Mi8!tnM_=BpY&=b(QuTJSgj3qyBL0&oSC8(?<-F} zJ#DkkyZ?^tQC5Lbw0)1_k$vf4Z$HBlV?JpA4krN{_7OC0z_%=k3^M5|zX)=yd|8O+ zoc6EHfI*Xr9>O+&JhE-bP^yd-@2YrRz>j6a1xCc*si1bM*N+WjqUG0iu2Z;_PMR4& z5rw_?Y>673-Ya*`Urvm=rEo?a1(dQ!MOk&|y!Pl@jNH0k7g$j~mzoqA!w)RuzBkBP zvxEiT^pE4HO^V=*l4GY~h_@l#c0@mGePgqgtN99aHQ;@tF#IEfpNKeWcB^DL@!WBJ*~2MSSC?M%gvI=C08 zK5pBR;BuI2?!kQ6TDUZLw@$j^>0SvnTG9J;L=`{Jd4+F&zfX%wx$QkGVH#rW839h+ zpmV&-zvq@th-ZGsGV7VA>1B>eM7q$aS^ob8Q-kEwz$`t`I#NPOVTPLAcw&VheE{g) zg+UC?Aj-?MhHWkWvD}i9md$o&K%wV#n>Q+t;mW;Nbv|d%@HU9MXg^60svc3OLS+#s zGS);h&X|^!Gwey*6%imYhl2+L-jkye7Fh2EdU%uZy*O(rpJH?LsX~IhlSmlXL_DD% z3A!hKE?4`BG)y9kRc=+p3B|t?vKjGM;2)Fe9cO%i5P;kULV%v9i74YU7_{@7)iifc zsD2~}!56Y06((W)l(1BHYvI~;tk>({da|j3yMX|6W2l_zu&~@G7Wm$|fv{+<`ZQKw?uY+QinR1i^dSn&Ge7QPo z!H9&cERc^5E}~szS7(_-D$|=f)lwmzvWt~tRHW3X#cMbt(9JPYHT(4L?|}J0ZM6inob#)2JhfTU z>oT&EMDHaLtDPokL()E28n}NR7jjgO8f>u2twQfF5H4J_zZuVGrEy)t6- z7GN95)8-m0axy3(Omjuc)esSLMK@?hDe05?WMj!fa=C~fnWe-MSncpxjqqlTx$PD& zqS0%NKMMhup-q2F*F|?Qjr)4>nEcKKXw<-qht0yhUDh}3q*s5s$QVo5>o;@1@KJ)q zd}z_S^C=VV&%H)IDcbZz6R%yd-3dkd2tLMz^7EomlkwSk(lqIKdmITf z5?Ugep-;c}Xlc7u-A_fq3}gv4vJ&(CsjpVG;n&ln2G{T_)mubzdTJp4UjQWeNC|1Q zL>>mUV8G>3V(OrI#|oqa@U1TV_*1+2sI{aKN+~-jAFO63m0gEONs*q#WRr3DCzKyt ze=h|Foc@p^bJn{@I_P23vf8?#o=CA&PJQ}dh^5lk#I&g!l;e*Q*( zH0y3n|GCfaWd!hQ4>&+td7-bWJr!HpO=`qwDVj8Rg!(qoY%aNu&qx*T)4$F(CXI{G z!{F!>(86tENekm|Okm+90Vs3DD!>^-C#7mDxRFAc@Hgp25QBCoG`p)5-m?O zS@^i$|FopZsQPbS@hm}GX(EAqWMKLnrm73GmA7dCpR>+uyV=-hJS=q5ce(ikQ>b(Z zDJS|uXeEZK2%QsUC(uJ{u}xiE>aLb%1_y)u4_E3AD5OAKMZe>!-WYhP$6}zmQqU>K zn}9L|jk$WDqqEPe-H;Qh8Nf zwUdYJERIE}UjENbd1>3gK!!rTyXl*xMKDes<3UZ8d2KU^I(7;QLLSGF;tw6n{Ud^> zDos3z)FDvJIn3IganXNOIA}Y_YLHAUzS^w%O04ArQGrF=Tv68}|fS;JqBSJAKdf;_=?2P6Q z-p$UO6!z<{fMQ){p}10%5q!3R8bvKzvCQKoS!VA&f()Wq+2BnNU8KEI4={tDP_6j^ z@~`PuV$Tt|8}LU4u3n3lCeF)PVcZG+<*BNqkk7La^+8CpfhK_2XzZOmoFZ?6)yk9Z zTPN~jx`F4Y+Hiy-z#5sT+&#;!wzLb>J7bgF(4Nd2mWU?xlMCxLxThwU|AbNeoLkPq z4;@tZ0-}Q-#)v!r697sVMbq;kdV>W<%6ndtR4tQDweFsbC``&`A6;3WlFWhx@N`O5 zTB3+|BWVl4Z;RpFX~`>E)m%84^67ux4qlWli0NQT2n2c?>GE)XY%V4yz`|%s*eqlc8@W@|xh9qWWhWY5q;BS$=T{DDr9K3P?ya0D(%;8;UBOL?lDY7{&} zfSnS{hfY2;x{LG4Ip>jcYYk<6JualN_HtGD5=qHt0;jP_S<}J6xeoxrzV-0EJZ&`l%rQf;dYW<-R_6%8ev}PB!3T{C1xCd*o zlMWVB3AhMUls{UysL?6_!fBwlcZW@rVHaJ}Xu|MVM;s`7H5CvuLcr{)hV@ljvYq*h zI4U{Sa0fM^-VB)0%DmNTYA!CHIUK?w>VL2?P+;Hte~o>0SXJNhHwY3+NQ!g{NOyyD zhcpsOcO1I6(%m6a(h|}Q(%m4^Dc#-mo&(-{z2EEeyg&Zf9EN??n)R8PwPwxC+FSOv zBZdR4HtpHQudL_D6K%;@0^MH_XMGC0DffdfJ3_s?nFo}eBE1`GlhOCO1BYxK$Eh1d zflHBuym!{^p1QoHf?>iFv$}2iTmA9F*4C(Y=F_tL@0FJ&572qkw!C6d5>S19p9(-Q9o@^O@7XaU%+)!l z<&F7h`i&<+(1uPSZcCV0C?hEW(I09}@OMVc>Lm^kx%SJ>1kx z=r@j$nQPS`8ksj=4?hH*h(olfEctfxWVMFGux!K5o}p@Gtuh}}YuUTHRp)Sr6!mU{ zg~}{E4%79loc^r0|CEI~b>na+x6Bln#EJizj9(vkQmjmkDp#hH*e-pEE+fQ)~ zyT8uy?yAbx?M(Q^3K`i8pITld+&UeVYgiMij=oxArHF<*0f;z$psUi|$I0_0=ZD@X z(n(4Yun485CdHUyMH{BD3gVLYW>H^RMmMa^diTHTbs`tB+f#9R>^diud5A5%ukI zO~*5U#Jr4T@9uZ=cQ&(iJABgz%a&s%dKBEUHC!&?uy1W`J-M-w9Wdk=plCNr1tRGg zK7c5+?}w-94*lNaImA#HJ}_HHPe}7Ac5*!h_F@3ftgzLV**jT!L2uh+C&k>LpJpX7I+?;Tv>DCjR0kfxtIt)8NVgfuQH zE-ck!!((_9$&&MM3IjWfv87)tWJa`EVpVbFrZcAdS*S+U8^)rJgt!7qo^h}ZHJ5#0 zk0@N14jU3PKKPV~O;cr_+OfbST~ySnk8&b9n%o>Hq}%d(B?rNyTR)aG6RI3_Z_)8{ zpAo$y#vogaFd@hxCV+f5Tt7w+xQ5EK+pa6>xWP`t$s33_`#6F@(r9$pl1>w^QJESO zLR0GnadO2O2c}Md)m#j>ukw|m=%hFE7;=B4(6uJ9-bOvrT@n2PXBTFu{#!d*Yr2bV>l93p{K~-Efn>Y^ zemH7TbZUZajlkoBY6ESBgu3}okAn|SlddxdS0@0hrOVczps7PDS>=s!YRaD&7rh#s z%S4TdUmf*Hqs07PV-tsY)+>*RKkE;Mn)+IV2H0$(HWzAZl<<$3RI+LRsys zWw60+)x(Orfp%mg zY29W>LdT285j5mV+iUn)nF|P%3O`Uuj?R3NSNaxCP$MxqZcV)y_QCHgiAj7zb z<2`l!XNG$B*uk@J_BWX}QohI(?Q`29O){D&de2mp2a!n$ZRqs(OF!=6bxeKiZtvr$ zU-qmy#rqHxOs9`icPr1``58p5dY3iK938GlBCUDkSfM6sgpG9!~`zJhH-S&CC(Wm^C9m_;b1QWVKfkbzZvWwX%Fa z;l;I}!~k;WXv(wLOl?AqeCla7WRTyfD?sP)1J}6#ArWFTazS5q^&4S8(jqW@rHet94$iL`t14UK5D^*tmZxzz<5ZnzLRBd>=J zsOU=P8NG-g?_V;U^>I*o;Y3j3=idf@!U(Cs5p$Pw{RCm{U@{hs`vCcQUcy8YEaRS< z!`1QZvVWsz64mZ`b9#tJD|Pq$)J~;Aj}HxnaE_Ho32d6TvTSm$MCim}j(|Ikvu3m{ zM@{zJ7!l=@z`$2i@VzY3@F85hihwPGMWf8Loq_K=E=1ReTLM0Q`1};+H?&1RFa?Os zKLpd6Xp$G;5au@|1_UU``FHD%F9oFrL1X*(5XP^K*LDtp#}_PYh`M`mHmx7g%ErV# zdMJUwmFfek;rlKAFHB-zygN@0|4d5ceB#Lb?q714_y(ra7;NY}ITiqym@eQAdVrHVxHfMpN9ea0&)n%5M z%OeW;aF)pTk%)(LE$_G!>Zd4UbyL>uXxG!g`V8Z@`3kJdHsjjPR?5TA2*K8PJ;j?t z_&QQsQ@~p7s%YL(0D!9WMkhf62cZa#xTSlG^CSs!XnQ>{B6v;kqJ9?GTeZx2WOGXs zfrVlLPa$+)809F3p0=xxJ%^SaCl}PRllnnGL`?eNyJr5iJx>q3B%Og}35>4-YDxIE zZX~+bs?au%V`5z5S* z7>suDHr-X^uWX=C@1D=$sF-^}!u^e(IBHQ%5s9eEA*uB^-ni6e=nDLAfs9`=MT8<4 zdt6_1#xPEO4V8#drt8MIG*5~K#T7Uk=(AKX@`8j^w#I3_%d^T?;Vq@o4O1fB z6MWi&M~F>6lNaeP9h8pkM@)a|gN0PmRrgC8jd)nVT9uij;#c?Q>d2R96m1s0(#Chs zl2{HxhOenY0nxPd1hp=IG7YQRE-XLZ<_Paa)<%u)cU0u(s|c5!mT4nR*zWZQW)1EF z3q$?oF&qkv(!GRG;=ApM^WOO4JKx7!0`g3^u<|Eg6Q<<$W`5$a2fzBr>HF2-P4+E| zbr$8bi^!Df$~_d=(=gBT`MbS=Pw-oOoI8LTFUsFg@^f|nCb{{|OE%S`VO&CHoS4Xaad~Gwk)5m{ zjUS5P`!N48dpi_|4ckk^)e2{V2SnsF+@Pm7Ly!Esb`rNH|6Y3G6~-y;I>2M9(2;KP=ZdRIIP@d$ zSI7`kP#PmQUH8Yz7l}f-V9K7c0P3Qe^2T;y<4+#r(R1{Elo!XcSb$9Icdh5gQN7O8sX}~+ ze&FTPeUnm9JsUBwcZTxK)Me(AjF9qP;;>C(OVYAUS##&E90hqVNG8+$GmX31^H8mp z9F+8DJgGW`#wB(O2OlYlzEhDAz|}NUUIxqprsX;HscO?Vb~P#2H~v?*pGus7G9UCU zr%kR5Y>_U->Y)RfJ>as{{-{QaPi}X^HTnA3p~_m|?x3!_zi|Szy<3#H=8<|xfeObH z97IlmEodji-r;F*)Z3xuI zq^Es-ENq8J5;TyPm;Y4qn$sw%@fD>8ekCnCH_bG0ep#1#hK#wh#IV9BWLU`5Q)eic zJJUb$pDUDqSAh?5G+D-y)q#OI!gvvhAiaDnPIE!=0;xQhKq0o3cOtikNR0&=Vw=;s zo4QBRbsn@tTc@*Vi}hFK7ec2%qLchIvgWS8Wu1J!W3T#$cHM1_EFmF@AM_fe;bc?H z=sw}?7?5Zgnh1`nWULWkcb>asI(wm{+*-miGKS)^pt`@9Z1LFs2jbr@l$XK)p?jUs zFLW;(h1U~^EoqU@Q)~{`bqMD>p4uZ7)XhCw+7QetS0OA3dgKTs*JOXED35Ubg`^z@*F1|>z{VO*4{ zG|^Vlusr8P30Mx5;;@2j||^0-oEFw0de(yz7hcb9e&5`ORCxAxioK z#gVp9`EM;>4YR&spc~8LbWWB^Dji7%T1Q|ZNVRf5h7>zylq;mM*3mAYOO^R2^C*1& zj)rMYdTSHGhdl5hR=^(ZTFvakEh9rcX7GtI<}9UX^vG-Ul3P-Av0)vLPJIVdbay#G zEj{}yCl3E*fG0aMIiGK~x}xuGj0Oe)K5|>c^gFm`DCT1XbI2p=4uifnZ=W8#iuB`; zW`^s!2=M&I=i4++9 zjude+DRP1^yS=`vJeMm6I7oe?(m1*d$E#eu@Lg;pQGqR|dRHvLl#CH_RYYU-4)4`= z(Ei6~26<7@lbN#dP~J$Qo6y}BwIHWwS|?&Ff}}h`Ag&!xWS1UK8Ul+d5C!(b<~?Vd z#OsCT$H62K)5X z^`L*d-s%O#6I9$!-16yZR~cE+gh?N#H7TNHV|skPh}>=_#6Y~Np3R&j8VeaDRXcvu zfw5VihGd&#rQRlQN#Bxug^#3DBg9LF(XFPB`nZRq^i&S znen6ztgx}{&GK4!bn5Na9hHyu#Gp?i>~2i3C>087k+&&lA;NvS$B~m}ZX3@3FsB@%<*JFPI#rOmsz&Xobt`Cmu?%G^P=Bfhv~NXU*Vcj@D#&trk8E>xN*2K`I( zHnS81v|ta`ha2w8Jls>M+y#Ov+vf6~&QIe7`a6sn^1EsjI8*iPePvxU%~8;C*BCA1 zsdY{>&-;#xRHIs^ugbn#`UED~?gd%5r$RwT>a&`d={8Lm;%JC*KrjATql{}+M&P_i6a+r zSN#M4nUNx{>a__#Pm&~791cZETM#Ltn-IlIZ}%(bTO(3Nh$!3V1oU3b-;-0e@-p2m z)gd-mt}+|M){9(uD5g7Jy3WC0j~oL6jWj>skiZTu$Q0s^;J$k>Wb+`USow;nk{&XB^ooX`1jmHo+Y7v{f3@c8#O)@5U#M@1n0u) zG@@sf-i>;Pf7v29fQd7Js6!hnX?A>ZH9xwFsaR=2Pj_kPR=^w&_L%W1JZ<-HqdXUk zG&s+YVBY>#yYHP9*;quF*dIT;Oc_UHMRVru`62f4`b zP#B!l9g)k&hK@w{3IayFOUeZ#9i=?bYmlj|su6|pqlI+$y?7Q|qLHV5u zynTxKU6?Uwu6ZsG=8g-=GUDlqRG{?6$me$eb+hTnaA|@v!#5a%%uuNO7x>vda(KnD9|hMYxcBp5u+jms(BZyCZ>1OpZ6u{S*tiD0l#LJbah?Q z54|H|38}G<-?ClfG0WG0SR^P2g_GM2it~xqc*AQD1hMDWnFH*~ik#q&-s8NcVTK{< zV>F&N=5!K9cSB}s?oK>>LhjcNTfC-JK=LBZjA%%En zj&zU&i4hl@!{T$c&2>@W{~~^8^RzAkkvl{#p@(g3LRn*6bRPa!q?Z47{D|yfxmQS% zjQY0^bB;lxUe*GO8}ZDcGW7I&d9uGEWOT@I1#mcUi6E&qY=grUp!c~1#URgR*6i+V z(T=0=>Gay{Tpt$aIUyKhlEVFK#=t~IGD}Q)$(V7rih)ue1Hq^m6>T_41Gz*39KDst zY6}Z)kTq@T3B@_Tvy0sAnN=uN`$|z*9-P*}BQm3rV%B-3W}xC7r2vcJ?$5^uDzrCu zZ$!}ui{`Q3Zx8~Y#=*$M9$Y1N4&TRI32Lvx(5eO#TIp>VtwJ~j4N`}fWtU|LDQQI2C&UIFb(kjPYV0Yb&A+?_~VDinH{*u@Srdzuhw3I z6c~7YgPDEX`#>TErntJ-!i{IB?J+#(2YiUSV!RCJx6vN1;nmB1pBS~QE8+3k@YzZO zkUCUh!T%A(28!$VVFE`fD3|x)BaZKR;>C2D98Uvur10Py*Eg#(74Stit^9Qni5}$% zznP7{6U6VsmosY`>j9a;(mQY&B&+yyEvxeHcg1^#r6Vb8Y>g;my34WdvJrFy%bJu3 z+oPy0R$KVjtv9JGbr`ln+^=}R=BLg4gp3mB?h7!Ng2~b<9fG*<p)<@XLP|8|ecZjWflPbm7@UGfW`0lO&#v7PBK_2P5B@re@ zUtY~!6avjRpB=i`c)lA9ISVo~@(_&~mBpBFlo6nmR0<%`TX0wfu-ymfu%{O%3?X$} z6NR~asvM@0=mOS~F|qvJ8orUV{TtCE2@i1=Nr7+VqtcQ;( z?E-vIT!C?=)i(qRiMVRCay5p8aJ9H@#In47K^;wBgojGUe-1ko&VS`J&wi8ySIdRA zPbF!ifD-iCX`>iF=4tPOiLrm;LKE|n7|%VL`Xxvx{C<$5PV;urt||$mrW{Pk7#pg?BIN$;E9AE;wZF01}qW$>4H9d9LRL}F|EFJ!&T|5*Cw_$AwIph z%NgE4Rv(g$!iO5$K$6lSkHsYf~Ko5y)D5q+SrD9}BTq%p`V|PaU3; zc^{JTE=g{3Wq`Nnow8E~h6?Pl) zt%J~08jfGZ`njD3M3tKgLKxhPDPK1u!g^w3h48%r%SKa_0?aTxZ)C_`>s^bK5C;Pq z8Iv#P0>mIl^bUW#MD)%i?iX9qX<-!M19 z7aQ*Ify)dS9_?g_TTl#U^_7%yA9;gm^fV)FpX08K4_V=0^&84hCNlx%5H2PMM3@g< zBh)fH3aZ|@sl2V3uOvp$4CxY);6&g-qGf-EIzvu77bs%-B7%013|&q3g|BW`OLCu& zk9RQ%@L+dBieAO7;|MK|X3LL#mLsw}a6U?=y1ij$!-z$@JW2JP>b}r;lPZp!gjKxJ zunO9)^q|)oyRI&oe$bsU_^<_tiaP^!;hN;MW&t9CxES2#9uo>bvyq?TGBY^hHzPlI z|8$NNUOeuh2v#{_I>i$^Kx7@&7qR-Z*wHyHHP2(A)w=Ox<_iwRk~}iHU3d-XU(qlw zHMrtrED@=gVR>#0Z?V>tq~*8KHV&j*#^8xeyR9_#N)Qfr!?#6Wyw3eDFdDXd!(sTu zrAtHn#s~i662_Y>d+UQ0Wh%_~(In;I}kJ@cTQHc`#Dw5+T@MY{FzTEb% z_A3gg&Pkf|gRM5_K3DwjU`UTsM{GH4Bc~T6*uJc44cpGtG;-NU)VH?SI@^Wdp`+f1 z0rkznqU^oNE!)?PewZ)I?d&sXq+a9x5oN7(|tJwC+ zqORZ!)Y=1?R*e0%Dz(>XO-0tX>nyLzCwHAlrD=PwUWzi|v)DnQu=zu#I7)pyN(=L( z;_o2zpO#`hJ*W~@Y3=PFjZm7>R)6P|0C=jj)kSlk&pfQZnxIiak0BF2lbX1xe zFpZe`%d3!DsR$?9E|HMg+A9Ok!S8Ck7)k*MjBr~Iex17Q2E|l zwP`~3F4Jgh8^0BJd6q9CRg=iU*)pvQwMs%Ys!;_>+l<}YaO3VddnLDEdPXsR_W46w`XQJf3l2w1~AI>9F z1Ct+u$B%M9lB_Gs#(;w-p#TMWPjesG2{kt?>7ik;Ml z5-DQT2R%W29i!<*QY;w@#kRkhcoS26xX;$o17_kqrW^iVLI~*(G62_H@m8RRfiq%i z5sq`exBBBK#H3l|qQ>~6{Cgr^SypKXoc-)~&G5~N(6;XJHOqI71Ps(2Ba=FU(+@>`2g zcdFjhFE=C`!18K|%Txj3S+o%U;5LG$-rF`BHS>U{4BKXNona5k7StaX^ zOY_2hbkVW}+iWvEtOJ!cu@g({YUz$nt(CHpljLlHQ7;WPI^Cn%9Nvzp;E7T!0Py%! z4-0DMfj2r8{&%r2#lmDL*YCrb`GRUiA8*RHZK8@O&k83V$GNqkifdpmJ%t8TZ6vD0|r- zPj1439i3=UKrSr1ZjogQXi-`wBsvk32_t+{zv6uP98$+P)_@+3_gze;@H<+GUC}%A#sDD~!w* zqEVwTF1phqf@1UgGN>Yx$uZR0$1lFOYQ&D8Fte_`4!04Z|1HPS*npXJHd5Q2&}v!- z|LSSGcT}yeZ9a_0#!-TxVa*W4b9y;;qsC|a- zcDPXiMY<-3XV|XUBwpTp1iRTVqM>-(h!Cr*Q&O&&QyzuWEkXAWMbsEOnzroa47p4* ztU{bjwo+cPQo-1vF+y)`PJ>MTSFc<&#zu9z(N()XT8bM9ekV^+gP$zz`!T}uJR{h~ zhU&Kuq9NMVp)Pq zXu01tz$RF!@9YV0x7WJ6i{y^AN61`%gpqy>d$dER6ppo%r7FJ@O?4O#kQ?I>I;33C z9+L*@H4$+Z|E_ylLZv8Xbq#G&bR*-0{`uOOg=-sAar$F?-*OEy9DJlvtqqP?7pc7b zcq~s;!?7yda}GFDZuRY1>KvDiUrkc}k=)xVA$aQdNH$h`QD|3d%kDzXbWOBTQ6Gni zg5UNXR~~NI4&=-B?0t^s3TyBIuUHBm>X$ARNOrY_OMdi6UthW;ue1$rjl6p)i~r&L z073kn(1TCjs}bajE3AYx`+gl;*a@9^mH~ecI}NHV90#1Ky|0Qi(h5`$RzMhX zL()q*IDmKBR>m+#>L2lYN}vNG~(^ zy32I$mX*IyBW2XHAH5+I9>@8tw+<&+CaI!{o(ol z+{a}Qf^y5Rw@xU0A8bhkt&lT`<-FcwvJXw8_OoKN2ZGah5EG2>iQwDUuUE+Y{?jvx zyM+oZj+4133NdmyJ`~JVfWWOK$KPv|ZBCC3^iY5J@aMuu@q%_$hq~nONJ0 zko~Nf>?uipgy=sI|1%8t0i3I(XSE$en8F-5we3U6K49QH9*AJM0pMI4?tpXpc@p9& z7sVF969<4{rkS70a2JQox zf8z_YCV+^^{tr<9-6Qaaf<5r@C#rgXK{WwF{8J@@{!c2={x_9q=hyvjRR7LBWJrIY zs`NKh?}`65bFi#Se#<&KvIYbAJ?|KUHAVLyW76#aFS-%n>!0`-{Zk@f`?Grj))xr< z_hfg##qu{sSe8jW+lKx`Q8yL%U*){#<4+j<{sN;hg!rcpy!b!q0Mb8o0DzeMJ@pS5 z|IR&RNPocC_rE4Hv35`V(_&ixCR_;dx5WT{EGgj012RecIeGZKfNaws*FWKcnC$=8 zl>7cA-v5{~n6Jp-b2Q;ULH*q$@aJmuz{j7ca{Ud}d*UA^v-*Eh3A?|kgdOltRR797 zg!m__YqwFlE#YY2UbIK{*iG~?F`K+RMwx@Ynw$wi9R7R|Yvc|lrn6yC^}`k?=x185 z&h9Er@8+yDT=xPogIE3G`6msta+Nz#?7%0_yJllhbwP5!ewki(Y0pV`;?A0F<2ycn z8OOVAflnU5kNl)~@L~6==$rAJ)4}=jJJ+eoI)a-44qDMIKf@o_M;ymS9CvR$O>VD| z6FVp@w_LPuS5WUxg&iyA?lv}c?{a`ElDj3K9-|AW-@^Cv>axCbJzBb}wMX&7lojF~p)p<*NKc|45E?5Gd-qFc*Ht)q-aja6H(b)0pp*)4mF7s5pwP!7>a_0H ziOI{8)eF%4d;m#i!{}u}gMHhNomJD?i^DFs*_*}Ir5{JPWZ$2z2-Dm-m(5yLZW8r^ z&s(nC)Vg1bcLFz}-_+`E7EvyM3p);iy1NtWy*s+|lv~P3j;=K|z!_&|n8*>h2&bHy z?zFusPFJh2ia$=T2XbgE>RivsJ?E@bYE##HtERTk5(j@($y-jAYo6kHxW^^->)aj| zTA$}Q-d(e%ag=(@I1$`lB$Ce0(H>o^_XMNv z0cgmFXpY{EdjeUX`~$(Ep9cZ_54DO~mY>np{T%mq9rp91K!`o`q>1{KP*8TSqWK3n z@Big8fcHqOF{Dw?Vi*KCcSNoo*BTq|MPMHkH@kb3hJG$p@kg-J>;q&4gClc z=HHB}Jy(Xe&4h-6qJ)8hLItz`ub&Ulsy)#Pg9P{O*bL%5qU?(f9i$?L@RGHNr%nX^ d&U;uWD2#u70sQ*|G)8~)&p`?}{Q(H|{{aL71OEU3 delta 47066 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 diff --git a/spreadsheet/macrofree/alz_checklist.pt.xlsx b/spreadsheet/macrofree/alz_checklist.pt.xlsx index 758ac528c020a81f00b335d92a88c58a6f245c7a..45113d5334a7825a7618c0716f291fed219e10eb 100644 GIT binary patch delta 44430 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 TI;b$dw8eRM+{UJFM-u)&lZ@}O delta 44138 zcmY&<18`m4_jcOYXzZl18#cCW+qQ8UtFdjHjorq!(b#CLf6}+V`R1G1ckax&Yv!)K z&$FJz-4+U37z_$8CkYCM3IYNG1>)pF9s^&Y`u3$Ngue_9`{C{BM-UL?w=W}GLpcXq zJ4bp$TL)u0H*2fFm{rMM2GpOg2~)Ss(!7O1m55Y4A>iG9Tbg30jRsfzCxK{FaX1TSHcuY0ReEwyb2>8t`l^eU!4o+c8P`5G~G~mGA+!+CETHzvQJsF!{UC&zCBN}!KT26J-f!nboCE&65l5_s1m^MoL z73BXrue#e0T@WbmCnge6l$BEg0&+|R27(C^2iJ=&vE6PRmnTxo`lJdayJE>{V4>00 zd(qL?I(BB=&WF z{B?D&bg5%}KS-8M1McMstJ3{5Z@_ZA$}F$`zz=q~-f zVH6FPN`HQte<19%xjHlL-<7jo{=KO~z|-w~30MzjJkdWdtp4e)iM$#L^;$;6UH=*~ zjj;6{GPGUQr^)UF*6`~IrVVEhCw}j>&f?nE6mttvn+udJ7Xa2N_$l~&ndqsGC|5P7 zJ!Ex)OJpJv`FlSU=Q*<{cH06T-DyQk1xJwF{GS+Xc*6$D3U7l z6g#OSx9W+S<_7d{n0(ZWUX4N7V(0BXi;E&H;&D%OzBE_zs5N|r7#M`s$)GDSr5Ve> z@;YF7Rr!2I_1d)34ZHQ6vuig9$^CSFy=ORDz6_c8?5M~Z%)5?zhxMUla0$6XRb*k% z^5aG$c+VHR`Hz#BZvG#5^}3?4H-dBl;M2;BfcAy-o)y5lZrD{3K1u-UV-~EDE?vh> z+*NomxITmc*_q%)9a^OK^t)Tn2QXfX&$1JCb#HF{@nYLxI7fdR)A{1WTZlW%*@`i+ z=Q^-wyS+EIh<91d830$$^{UluU(~u0PM^sgxc)h7eQ10f(AvHt@Uq$+fKJ@YqGm#T zNP!#}i2=rKL5+3?_IQbZ)5MIcUOJLvf}SyKn8K+U^5uSrZ~fG`z0;X$ftW7Sih~`7 z_^}Uv&0ciTWAxc{^$NJ3xa~*fyu7)L;r7?q@wH~@U)Sb&iDXgNJ`F5;lqP+VWLvlR zQ(1Do z951};UXpNJS#r{9UbRG&f`g>fErXtx`W^q}Pmlf6*px{}*6PUUiJpik6?!2wguYcv4TJ?>p?G|moFZ=$v@;1YH z+@f(<;(-m%n!*&j!xvuB4bs1LeWxID#3v*=&nIXwXk8h-T1?)Ad0u@lY9T)n1>{wo zlM9R|^|hsWkwN23$9lNDGPU$;+feBV{4x+@=qR{(vogWqxxtl+w-NPdm{ONUs~dY2 zYPJ;c>>NqaOC@9r69wZ(^Hm|kI%M|;#b z8mEt2?CN4u!lx+xl7b!e(uSt`M{ayrE_a7Nzp+4&VDo+HcMD_xrOMh*9%0KY+G_@M zh6dk9eXhf1t>%2mZH&~kn5-{#^ca5~x`&Q@@{zj>de%0DJKI=Pv|e1APQ6Lgyz-5T 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 diff --git a/workbooks/alz_checklist.en_counters_workbook.json b/workbooks/alz_checklist.en_counters_workbook.json index 864387e10..7103ef5b9 100644 --- a/workbooks/alz_checklist.en_counters_workbook.json +++ b/workbooks/alz_checklist.en_counters_workbook.json @@ -1265,7 +1265,7 @@ "style": "tabs", "links": [ { - "id": "5e1fed78-c6d3-4899-b92b-6422d13fd4f3", + "id": "22494dfe-7c95-4b33-928e-0f4e90d60ecf", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})", @@ -1274,7 +1274,7 @@ "style": "primary" }, { - "id": "b952a501-f86c-48f8-bcf2-bd4075d1af46", + "id": "408e1fdf-bf32-4bf8-841f-74b20829fe5d", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Security ({Tab1Success:value}/{Tab1Total:value})", @@ -1283,7 +1283,7 @@ "style": "primary" }, { - "id": "f3abad1f-bec6-4a13-bdd4-bb7046b0631b", + "id": "c407200d-7371-4237-a27b-6a12ef0e6c4d", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Resource Organization ({Tab2Success:value}/{Tab2Total:value})", @@ -2303,7 +2303,7 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) 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": "querytext16" }, diff --git a/workbooks/alz_checklist.en_counters_workbook_template.json b/workbooks/alz_checklist.en_counters_workbook_template.json index c27dd8410..6e8e0bb7a 100644 --- a/workbooks/alz_checklist.en_counters_workbook_template.json +++ b/workbooks/alz_checklist.en_counters_workbook_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"Query28Stats\",\n \"type\": 1,\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 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\": \"Query28FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query28Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29Stats\",\n \"type\": 1,\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query29Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query30Stats\",\n \"type\": 1,\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 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\": \"Query30FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query30Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query31Stats\",\n \"type\": 1,\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query31FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query31Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query32Stats\",\n \"type\": 1,\n \"query\": \"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)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query32FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query32Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{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}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{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\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{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}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{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\": \"{Query32Stats:$.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\": \"{Query32Stats:$.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\": \"{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query30Stats:$.Success}+{Query31Stats:$.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\": \"{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query30Stats:$.Total}+{Query31Stats:$.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\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{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}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query32Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query30Stats:$.Total}+{Query31Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{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}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query32Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query30Stats:$.Success}+{Query31Stats:$.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\\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\": \"5e1fed78-c6d3-4899-b92b-6422d13fd4f3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b952a501-f86c-48f8-bcf2-bd4075d1af46\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f3abad1f-bec6-4a13-bdd4-bb7046b0631b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Resource Organization ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Resource Organization\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"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 \"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 \"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 \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/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 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 \"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 \"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 \"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\": \"## Security\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext32\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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) | 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\": \"query32\"\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\": \"## Resource Organization\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than four levels. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext28\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 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\": \"query28\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext29\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query29\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext30\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 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\": \"query30\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext31\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query31\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\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\": \"Query28Stats\",\n \"type\": 1,\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 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\": \"Query28FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query28Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29Stats\",\n \"type\": 1,\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query29Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query30Stats\",\n \"type\": 1,\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 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\": \"Query30FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query30Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query31Stats\",\n \"type\": 1,\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query31FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query31Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query32Stats\",\n \"type\": 1,\n \"query\": \"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)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query32FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query32Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{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}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{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\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{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}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{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\": \"{Query32Stats:$.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\": \"{Query32Stats:$.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\": \"{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query30Stats:$.Success}+{Query31Stats:$.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\": \"{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query30Stats:$.Total}+{Query31Stats:$.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\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{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}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query32Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query30Stats:$.Total}+{Query31Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{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}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query32Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query30Stats:$.Success}+{Query31Stats:$.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\\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\": \"22494dfe-7c95-4b33-928e-0f4e90d60ecf\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"408e1fdf-bf32-4bf8-841f-74b20829fe5d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"c407200d-7371-4237-a27b-6a12ef0e6c4d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Resource Organization ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Resource Organization\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"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 \"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 \"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 \"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 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 \"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 \"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 \"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\": \"## Security\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext32\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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) | 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\": \"query32\"\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\": \"## Resource Organization\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than four levels. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext28\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 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\": \"query28\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext29\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query29\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext30\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 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\": \"query30\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext31\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query31\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\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 cd0cf4433..a7f07644d 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": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -880,7 +880,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -918,7 +918,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" + "resultVal": "{Query22Stats:$.Success}" } } ] @@ -937,7 +937,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" + "resultVal": "{Query22Stats:$.Total}" } } ] @@ -975,7 +975,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -994,7 +994,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" } } ] @@ -1032,7 +1032,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" } } ] @@ -1051,7 +1051,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" } } ] @@ -1146,7 +1146,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" } } ] @@ -1165,7 +1165,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" } } ] @@ -1203,7 +1203,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" } } ] @@ -1222,7 +1222,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" } } ] @@ -1260,7 +1260,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -1279,7 +1279,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -1317,7 +1317,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query27Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query22Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query22Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query27Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -1336,7 +1336,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query27Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query22Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query22Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query27Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -1410,43 +1410,43 @@ "style": "tabs", "links": [ { - "id": "81dfc9a8-d2e5-49d1-be5c-09dfecbf0073", + "id": "1a507e33-4d66-400e-ae68-e5fb746cf4e8", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery ({Tab0Success:value}/{Tab0Total:value})", + "linkLabel": "Hub and spoke ({Tab0Success:value}/{Tab0Total:value})", "subTarget": "tab0", - "preText": "App delivery", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "e53c7b2e-fa99-4ddf-9916-1771822c0bb7", + "id": "c3e03146-d1a9-48ac-b23a-f5ce55536f94", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet ({Tab1Success:value}/{Tab1Total:value})", + "linkLabel": "PaaS ({Tab1Success:value}/{Tab1Total:value})", "subTarget": "tab1", - "preText": "Internet", + "preText": "PaaS", "style": "primary" }, { - "id": "e93897ff-1083-4655-8dbc-f604d354fc3d", + "id": "3b8f0464-c665-483c-ae47-a75c04b8c0a8", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation ({Tab2Success:value}/{Tab2Total:value})", + "linkLabel": "App delivery ({Tab2Success:value}/{Tab2Total:value})", "subTarget": "tab2", - "preText": "Segmentation", + "preText": "App delivery", "style": "primary" }, { - "id": "adc9e478-7255-4f35-b13a-8c62fe6e9cd2", + "id": "8e640b32-d254-4e01-b8aa-04146c7abbd7", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid ({Tab3Success:value}/{Tab3Total:value})", + "linkLabel": "IP plan ({Tab3Success:value}/{Tab3Total:value})", "subTarget": "tab3", - "preText": "Hybrid", + "preText": "IP plan", "style": "primary" }, { - "id": "f08fd721-d7bc-4729-bc6a-7181ff423b8e", + "id": "95abd297-d1b0-4fca-9e59-45108a80b4fa", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Virtual WAN ({Tab4Success:value}/{Tab4Total:value})", @@ -1455,30 +1455,30 @@ "style": "primary" }, { - "id": "38fcc5e0-e0cf-47d6-b335-20d2455a4ca7", + "id": "1e9b392c-4d2e-47e4-b355-5a621d36f8c8", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke ({Tab5Success:value}/{Tab5Total:value})", + "linkLabel": "Hybrid ({Tab5Success:value}/{Tab5Total:value})", "subTarget": "tab5", - "preText": "Hub and spoke", + "preText": "Hybrid", "style": "primary" }, { - "id": "c2a0650b-066a-413c-9415-5b8bf5672720", + "id": "c3debbba-c595-4660-bfb2-096f9035a0c1", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS ({Tab6Success:value}/{Tab6Total:value})", + "linkLabel": "Segmentation ({Tab6Success:value}/{Tab6Total:value})", "subTarget": "tab6", - "preText": "PaaS", + "preText": "Segmentation", "style": "primary" }, { - "id": "b8a515ad-5d70-4b8f-a6f9-d9dab2680ab4", + "id": "5eb5e6b3-f54d-4a0a-8253-6759b2df325f", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan ({Tab7Success:value}/{Tab7Total:value})", + "linkLabel": "Internet ({Tab7Success:value}/{Tab7Total:value})", "subTarget": "tab7", - "preText": "IP plan", + "preText": "Internet", "style": "primary" } ] @@ -1494,22 +1494,22 @@ { "type": 1, "content": { - "json": "## App delivery" + "json": "## Hub and spoke" }, "name": "tab0title" }, { "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." + "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": "querytext0" + "name": "querytext5" }, { "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", + "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", @@ -1558,20 +1558,20 @@ ] } }, - "name": "query0" + "name": "query5" }, { "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." + "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": "querytext1" + "name": "querytext6" }, { "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", + "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", @@ -1620,20 +1620,20 @@ ] } }, - "name": "query1" + "name": "query6" }, { "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": "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": "querytext2" + "name": "querytext7" }, { "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/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", @@ -1682,20 +1682,20 @@ ] } }, - "name": "query2" + "name": "query7" }, { "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": "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": "querytext3" + "name": "querytext8" }, { "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/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", @@ -1744,20 +1744,42 @@ ] } }, - "name": "query3" + "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": "## PaaS" + }, + "name": "tab1title" }, { "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": "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": "querytext4" + "name": "querytext22" }, { "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/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", @@ -1806,16 +1828,16 @@ ] } }, - "name": "query4" + "name": "query22" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab0" + "value": "tab1" }, - "name": "tab0" + "name": "tab1" }, { "type": 12, @@ -1826,22 +1848,22 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## App delivery" }, - "name": "tab1title" + "name": "tab2title" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." + "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": "querytext16" + "name": "querytext0" }, { "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/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", @@ -1890,20 +1912,20 @@ ] } }, - "name": "query16" + "name": "query0" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "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": "querytext17" + "name": "querytext1" }, { "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/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", @@ -1952,20 +1974,20 @@ ] } }, - "name": "query17" + "name": "query1" }, { "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": "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": "querytext18" + "name": "querytext2" }, { "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/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", @@ -2014,20 +2036,20 @@ ] } }, - "name": "query18" + "name": "query2" }, { "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": "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." }, - "name": "querytext19" + "name": "querytext3" }, { "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/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", @@ -2076,20 +2098,20 @@ ] } }, - "name": "query19" + "name": "query3" }, { "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 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": "querytext20" + "name": "querytext4" }, { "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/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", @@ -2138,20 +2160,42 @@ ] } }, - "name": "query20" + "name": "query4" + } + ] + }, + "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" }, { "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 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": "querytext21" + "name": "querytext14" }, { "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 | 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", @@ -2200,42 +2244,20 @@ ] } }, - "name": "query21" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab1" - }, - "name": "tab1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Segmentation" - }, - "name": "tab2title" + "name": "query14" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Ensure that 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": "querytext23" + "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 == '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 | 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", @@ -2284,20 +2306,42 @@ ] } }, - "name": "query23" + "name": "query15" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab3" + }, + "name": "tab3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Virtual WAN" + }, + "name": "tab4title" }, { "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": "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": "querytext24" + "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 == '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/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", @@ -2346,21 +2390,43 @@ ] } }, - "name": "query24" - }, - { - "type": 1, - "content": { - "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." - }, - "name": "querytext25" - }, - { - "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, + "name": "query27" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Hybrid" + }, + "name": "tab5title" + }, + { + "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": [ @@ -2408,20 +2474,20 @@ ] } }, - "name": "query25" + "name": "query9" }, { "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": "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": "querytext26" + "name": "querytext10" }, { "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/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", @@ -2470,42 +2536,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": "## Hybrid" - }, - "name": "tab3title" + "name": "query10" }, { "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": "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": "querytext9" + "name": "querytext11" }, { "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/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", @@ -2554,20 +2598,20 @@ ] } }, - "name": "query9" + "name": "query11" }, { "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": "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": "querytext10" + "name": "querytext12" }, { "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/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", @@ -2616,20 +2660,20 @@ ] } }, - "name": "query10" + "name": "query12" }, { "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 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": "querytext11" + "name": "querytext13" }, { "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/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", @@ -2678,20 +2722,42 @@ ] } }, - "name": "query11" + "name": "query13" + } + ] + }, + "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" }, { "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 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": "querytext12" + "name": "querytext23" }, { "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,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", @@ -2740,20 +2806,20 @@ ] } }, - "name": "query12" + "name": "query23" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "Use 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": "querytext13" + "name": "querytext24" }, { "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,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", @@ -2802,42 +2868,20 @@ ] } }, - "name": "query13" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Virtual WAN" - }, - "name": "tab4title" + "name": "query24" }, { "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": "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": "querytext27" + "name": "querytext25" }, { "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/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", @@ -2886,42 +2930,20 @@ ] } }, - "name": "query27" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab4" - }, - "name": "tab4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hub and spoke" - }, - "name": "tab5title" + "name": "query25" }, { "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": "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": "querytext5" + "name": "querytext26" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -2970,20 +2992,42 @@ ] } }, - "name": "query5" + "name": "query26" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab6" + }, + "name": "tab6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Internet" + }, + "name": "tab7title" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext6" + "name": "querytext16" }, { "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 == '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", @@ -3032,20 +3076,20 @@ ] } }, - "name": "query6" + "name": "query16" }, { "type": 1, "content": { - "json": "Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext7" + "name": "querytext17" }, { "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.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", @@ -3094,20 +3138,20 @@ ] } }, - "name": "query7" + "name": "query17" }, { "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": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext8" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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", @@ -3156,42 +3200,20 @@ ] } }, - "name": "query8" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab5" - }, - "name": "tab5" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## PaaS" - }, - "name": "tab6title" + "name": "query18" }, { "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": "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": "querytext22" + "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 = 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/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", @@ -3240,42 +3262,20 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab6" - }, - "name": "tab6" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## IP plan" - }, - "name": "tab7title" + "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": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -3324,20 +3324,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": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -3386,7 +3386,7 @@ ] } }, - "name": "query15" + "name": "query21" } ] }, diff --git a/workbooks/alz_checklist.en_network_counters_template.json b/workbooks/alz_checklist.en_network_counters_template.json index 1f77da349..7569e08c8 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\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{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 \"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 \"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\": \"{Query22Stats:$.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\": \"{Query22Stats:$.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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query27Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query22Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query27Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query22Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.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\": \"81dfc9a8-d2e5-49d1-be5c-09dfecbf0073\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e53c7b2e-fa99-4ddf-9916-1771822c0bb7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e93897ff-1083-4655-8dbc-f604d354fc3d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"adc9e478-7255-4f35-b13a-8c62fe6e9cd2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f08fd721-d7bc-4729-bc6a-7181ff423b8e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"38fcc5e0-e0cf-47d6-b335-20d2455a4ca7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"c2a0650b-066a-413c-9415-5b8bf5672720\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b8a515ad-5d70-4b8f-a6f9-d9dab2680ab4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab7Success:value}/{Tab7Total:value})\",\n \"subTarget\": \"tab7\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## App delivery\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 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\": \"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\": \"## Internet\"\n },\n \"name\": \"tab1title\"\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/en-us/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 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\": \"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\": 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\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"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\": \"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\": \"## Virtual WAN\"\n },\n \"name\": \"tab4title\"\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\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab5title\"\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\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"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\": \"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\": \"## IP plan\"\n },\n \"name\": \"tab7title\"\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\": \"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\": \"{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\": \"{Query22Stats:$.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\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{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 \"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\": \"{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 \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{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\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{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\": \"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\": \"{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\": \"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\": \"{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\": \"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}+{Query22Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query27Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{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\": \"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}+{Query22Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query27Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{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\": \"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\": \"1a507e33-4d66-400e-ae68-e5fb746cf4e8\",\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\": \"c3e03146-d1a9-48ac-b23a-f5ce55536f94\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3b8f0464-c665-483c-ae47-a75c04b8c0a8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8e640b32-d254-4e01-b8aa-04146c7abbd7\",\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\": \"95abd297-d1b0-4fca-9e59-45108a80b4fa\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"1e9b392c-4d2e-47e4-b355-5a621d36f8c8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"c3debbba-c595-4660-bfb2-096f9035a0c1\",\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\": \"5eb5e6b3-f54d-4a0a-8253-6759b2df325f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab7Success:value}/{Tab7Total:value})\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"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\": \"## PaaS\"\n },\n \"name\": \"tab1title\"\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\": \"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\": \"## App delivery\"\n },\n \"name\": \"tab2title\"\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\": 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\": \"## Virtual WAN\"\n },\n \"name\": \"tab4title\"\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\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab5title\"\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\": \"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\": \"## Internet\"\n },\n \"name\": \"tab7title\"\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 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\": \"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 6b852d98d..65ec0da3f 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": "0db54ed8-9ae6-4aab-83c8-d05b73995505", + "id": "cab5a7f3-2b73-4e5a-bc10-15dc0df178a6", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "Virtual WAN", "subTarget": "tab0", - "preText": "Internet", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "766e62f4-c04c-4a86-aba2-06ec4349dbf8", + "id": "baf36c4b-1078-4d2f-a122-b3942f69cb4c", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "IP plan", "subTarget": "tab1", - "preText": "PaaS", + "preText": "IP plan", "style": "primary" }, { - "id": "cb764f9b-64c6-47ad-9e7d-3a3f936b5473", + "id": "151c633c-4688-4c04-9884-744b07401897", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Internet", "subTarget": "tab2", - "preText": "Virtual WAN", + "preText": "Internet", "style": "primary" }, { - "id": "77991575-fec4-4cad-ab1e-8e66566bf6eb", + "id": "01f08a50-0cf6-4f07-ba93-4cb28d81ebde", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery", + "linkLabel": "Hybrid", "subTarget": "tab3", - "preText": "App delivery", + "preText": "Hybrid", "style": "primary" }, { - "id": "357f011c-74a8-4835-8903-15ed89603318", + "id": "93850e40-f0c4-4d0d-8639-77efd2956691", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "App delivery", "subTarget": "tab4", - "preText": "Hybrid", + "preText": "App delivery", "style": "primary" }, { - "id": "af0b344b-4335-442a-b97b-fd2c0118e31d", + "id": "d7c73b99-2f75-4ca9-b428-1260b1bd1ed2", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "Hub and spoke", "subTarget": "tab5", - "preText": "Segmentation", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "4ca6e45d-7001-4ebc-83b8-91744a90017e", + "id": "77b08c0e-f06a-4bee-b3ef-9ddbaf939806", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Segmentation", "subTarget": "tab6", - "preText": "IP plan", + "preText": "Segmentation", "style": "primary" }, { - "id": "df0eb2ac-4e77-48f5-9ab9-a7cc8efed9ed", + "id": "d14c617f-4985-4409-87ac-3ea075746c12", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "PaaS", "subTarget": "tab7", - "preText": "Hub and spoke", + "preText": "PaaS", "style": "primary" } ] @@ -162,149 +162,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", - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query18FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query19Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/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}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query19FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query20Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/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", + "name": "Query27Stats", "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/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}" ], @@ -318,9 +178,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21FullyCompliant", + "name": "Query27FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query27Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -341,7 +201,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" + "resultVal": "{Query27Stats:$.Success}" } } ] @@ -360,7 +220,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" + "resultVal": "{Query27Stats:$.Total}" } } ] @@ -394,7 +254,7 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Virtual WAN" }, "customWidth": "50", "name": "tab0title" @@ -435,15 +295,15 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) 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": "querytext16" + "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 == '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/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", @@ -492,353 +352,43 @@ ] } }, - "name": "query16" - }, - { - "type": 1, - "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." - }, - "name": "querytext17" - }, + "name": "query27" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab0" + }, + "name": "tab0" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ { - "type": 3, + "type": 9, "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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", + "version": "KqlParameterItem/1.0", "crossComponentResources": [ "{Subscription}" ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "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." - }, - "name": "querytext18" - }, - { - "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", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query18" - }, - { - "type": 1, - "content": { - "json": "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" - } - ] - } - } - ] - } - }, - "name": "query19" - }, - { - "type": 1, - "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." - }, - "name": "querytext20" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query20" - }, - { - "type": 1, - "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." - }, - "name": "querytext21" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query21" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "crossComponentResources": [ - "{Subscription}" - ], - "parameters": [ - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query22Stats", - "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())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 + "parameters": [ + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query14Stats", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 }, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources" @@ -846,211 +396,21 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.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": "{Query22Stats:$.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": "{Query22Stats:$.Total}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab1Percent", + "name": "Query14FullyCompliant", "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": "## PaaS" - }, - "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": "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": "tab1" - }, - "name": "tab1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "crossComponentResources": [ - "{Subscription}" - ], - "parameters": [ + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query27Stats", + "name": "Query15Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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}" ], @@ -1064,9 +424,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query27FullyCompliant", + "name": "Query15FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query27Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1076,7 +436,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Success", + "name": "Tab1Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1087,7 +447,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" } } ] @@ -1095,7 +455,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Total", + "name": "Tab1Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1106,7 +466,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" } } ] @@ -1114,7 +474,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab2Percent", + "name": "Tab1Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1125,7 +485,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab2Success}/{Tab2Total})" + "resultVal": "round(100*{Tab1Success}/{Tab1Total})" } } ] @@ -1140,16 +500,16 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## IP plan" }, "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", @@ -1181,15 +541,15 @@ { "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 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": "querytext27" + "name": "querytext14" }, { "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' | 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", @@ -1238,16 +598,78 @@ ] } }, - "name": "query27" + "name": "query14" + }, + { + "type": 1, + "content": { + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + }, + "name": "querytext15" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query15" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab2" + "value": "tab1" }, - "name": "tab2" + "name": "tab1" }, { "type": 12, @@ -1266,9 +688,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0Stats", + "name": "Query16Stats", "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())", + "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}" ], @@ -1282,9 +704,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0FullyCompliant", + "name": "Query16FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1294,9 +716,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query1Stats", + "name": "Query17Stats", "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())", + "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}" ], @@ -1310,9 +732,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query1FullyCompliant", + "name": "Query17FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1322,9 +744,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2Stats", + "name": "Query18Stats", "type": 1, - "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/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}" ], @@ -1338,9 +760,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2FullyCompliant", + "name": "Query18FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1350,9 +772,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query3Stats", + "name": "Query19Stats", "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())", + "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}" ], @@ -1366,9 +788,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query3FullyCompliant", + "name": "Query19FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1378,9 +800,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4Stats", + "name": "Query20Stats", "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())", + "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}" ], @@ -1394,9 +816,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4FullyCompliant", + "name": "Query20FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1406,7 +828,35 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Success", + "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": "Tab2Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1417,7 +867,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" + "resultVal": "{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}" } } ] @@ -1425,7 +875,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Total", + "name": "Tab2Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1436,7 +886,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" + "resultVal": "{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}" } } ] @@ -1444,7 +894,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab3Percent", + "name": "Tab2Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -1455,7 +905,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab3Success}/{Tab3Total})" + "resultVal": "round(100*{Tab2Success}/{Tab2Total})" } } ] @@ -1470,16 +920,16 @@ { "type": 1, "content": { - "json": "## App delivery" + "json": "## Internet" }, "customWidth": "50", - "name": "tab3title" + "name": "tab2title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of 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", @@ -1511,15 +961,77 @@ { "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." + "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 not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext0" + "name": "querytext17" }, { "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", + "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", @@ -1568,20 +1080,20 @@ ] } }, - "name": "query0" + "name": "query17" }, { "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." + "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": "querytext1" + "name": "querytext18" }, { "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", + "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", @@ -1630,20 +1142,20 @@ ] } }, - "name": "query1" + "name": "query18" }, { "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": "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": "querytext2" + "name": "querytext19" }, { "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/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", @@ -1692,20 +1204,20 @@ ] } }, - "name": "query2" + "name": "query19" }, { "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": "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": "querytext3" + "name": "querytext20" }, { "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/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", @@ -1754,20 +1266,20 @@ ] } }, - "name": "query3" + "name": "query20" }, { "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": "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": "querytext4" + "name": "querytext21" }, { "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/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", @@ -1816,16 +1328,16 @@ ] } }, - "name": "query4" + "name": "query21" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab3" + "value": "tab2" }, - "name": "tab3" + "name": "tab2" }, { "type": 12, @@ -1984,7 +1496,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Success", + "name": "Tab3Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2003,7 +1515,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Total", + "name": "Tab3Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2022,7 +1534,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab4Percent", + "name": "Tab3Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2033,7 +1545,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab4Success}/{Tab4Total})" + "resultVal": "round(100*{Tab3Success}/{Tab3Total})" } } ] @@ -2051,13 +1563,13 @@ "json": "## Hybrid" }, "customWidth": "50", - "name": "tab4title" + "name": "tab3title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab4Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -2401,9 +1913,9 @@ "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab3" }, - "name": "tab4" + "name": "tab3" }, { "type": 12, @@ -2422,9 +1934,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23Stats", + "name": "Query0Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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/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}" ], @@ -2438,9 +1950,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23FullyCompliant", + "name": "Query0FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2450,9 +1962,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query24Stats", + "name": "Query1Stats", "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())", + "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}" ], @@ -2466,9 +1978,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query24FullyCompliant", + "name": "Query1FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2478,9 +1990,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query25Stats", + "name": "Query2Stats", "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/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}" ], @@ -2494,9 +2006,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query25FullyCompliant", + "name": "Query2FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2506,9 +2018,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query26Stats", + "name": "Query3Stats", "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/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}" ], @@ -2522,9 +2034,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query26FullyCompliant", + "name": "Query3FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query26Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2534,7 +2046,35 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Success", + "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": "Tab4Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2545,7 +2085,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -2553,7 +2093,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Total", + "name": "Tab4Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2564,7 +2104,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" } } ] @@ -2572,7 +2112,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab5Percent", + "name": "Tab4Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2583,7 +2123,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab5Success}/{Tab5Total})" + "resultVal": "round(100*{Tab4Success}/{Tab4Total})" } } ] @@ -2598,16 +2138,16 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## App delivery" }, "customWidth": "50", - "name": "tab5title" + "name": "tab4title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"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", @@ -2639,15 +2179,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": "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": "querytext23" + "name": "querytext0" }, { "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/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", @@ -2696,20 +2236,20 @@ ] } }, - "name": "query23" + "name": "query0" }, { "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 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": "querytext24" + "name": "querytext1" }, { "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/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", @@ -2758,20 +2298,20 @@ ] } }, - "name": "query24" + "name": "query1" }, { "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": "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": "querytext25" + "name": "querytext2" }, { "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/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", @@ -2820,20 +2360,20 @@ ] } }, - "name": "query25" + "name": "query2" }, { "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": "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." }, - "name": "querytext26" + "name": "querytext3" }, { "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/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", @@ -2882,16 +2422,78 @@ ] } }, - "name": "query26" + "name": "query3" + }, + { + "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." + }, + "name": "querytext4" + }, + { + "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query4" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab4" }, - "name": "tab5" + "name": "tab4" }, { "type": 12, @@ -2910,9 +2512,37 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14Stats", + "name": "Query5Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query5FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query6Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/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": "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}" ], @@ -2926,9 +2556,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14FullyCompliant", + "name": "Query6FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2938,9 +2568,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15Stats", + "name": "Query7Stats", "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/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}" ], @@ -2954,9 +2584,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15FullyCompliant", + "name": "Query7FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2966,7 +2596,35 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Success", + "name": "Query8Stats", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query8FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab5Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2977,7 +2635,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -2985,7 +2643,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Total", + "name": "Tab5Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2996,7 +2654,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -3004,7 +2662,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Percent", + "name": "Tab5Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3015,7 +2673,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab6Success}/{Tab6Total})" + "resultVal": "round(100*{Tab5Success}/{Tab5Total})" } } ] @@ -3030,16 +2688,16 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Hub and spoke" }, "customWidth": "50", - "name": "tab6title" + "name": "tab5title" }, { "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\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", "size": 3, "queryType": 8, "visualization": "tiles", @@ -3071,15 +2729,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": "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": "querytext14" + "name": "querytext5" }, { "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/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", @@ -3128,20 +2786,20 @@ ] } }, - "name": "query14" + "name": "query5" }, { "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": "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": "querytext15" + "name": "querytext6" }, { "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' | 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", @@ -3190,16 +2848,140 @@ ] } }, - "name": "query15" + "name": "query6" + }, + { + "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." + }, + "name": "querytext7" + }, + { + "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query7" + }, + { + "type": 1, + "content": { + "json": "Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information." + }, + "name": "querytext8" + }, + { + "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", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query8" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab6" + "value": "tab5" }, - "name": "tab6" + "name": "tab5" }, { "type": 12, @@ -3218,9 +3000,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5Stats", + "name": "Query23Stats", "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 == '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}" ], @@ -3234,9 +3016,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5FullyCompliant", + "name": "Query23FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3246,9 +3028,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6Stats", + "name": "Query24Stats", "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/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}" ], @@ -3262,9 +3044,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6FullyCompliant", + "name": "Query24FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3274,9 +3056,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7Stats", + "name": "Query25Stats", "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/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}" ], @@ -3290,9 +3072,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7FullyCompliant", + "name": "Query25FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3302,9 +3084,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8Stats", + "name": "Query26Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,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}" ], @@ -3318,9 +3100,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8FullyCompliant", + "name": "Query26FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query26Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -3330,7 +3112,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab7Success", + "name": "Tab6Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3341,7 +3123,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" } } ] @@ -3349,7 +3131,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab7Total", + "name": "Tab6Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3360,7 +3142,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" } } ] @@ -3368,7 +3150,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab7Percent", + "name": "Tab6Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -3379,7 +3161,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab7Success}/{Tab7Total})" + "resultVal": "round(100*{Tab6Success}/{Tab6Total})" } } ] @@ -3394,16 +3176,16 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## Segmentation" }, "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 +3217,15 @@ { "type": 1, "content": { - "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." + "json": "Use 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": "querytext5" + "name": "querytext23" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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", @@ -3492,20 +3274,20 @@ ] } }, - "name": "query5" + "name": "query23" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Use 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": "querytext6" + "name": "querytext24" }, { "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 == '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", @@ -3554,20 +3336,20 @@ ] } }, - "name": "query6" + "name": "query24" }, { "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": "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": "querytext7" + "name": "querytext25" }, { "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/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", @@ -3616,20 +3398,20 @@ ] } }, - "name": "query7" + "name": "query25" }, { "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": "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": "querytext8" + "name": "querytext26" }, { "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,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", @@ -3678,7 +3460,225 @@ ] } }, - "name": "query8" + "name": "query26" + } + ] + }, + "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": "Query22Stats", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query22FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.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": "{Query22Stats:$.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": "{Query22Stats:$.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": "## PaaS" + }, + "customWidth": "50", + "name": "tab7title" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "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" + }, + "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" } ] }, diff --git a/workbooks/alz_checklist.en_network_tabcounters_template.json b/workbooks/alz_checklist.en_network_tabcounters_template.json index 906880fa1..d5805af3e 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\": \"0db54ed8-9ae6-4aab-83c8-d05b73995505\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"766e62f4-c04c-4a86-aba2-06ec4349dbf8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab1\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"cb764f9b-64c6-47ad-9e7d-3a3f936b5473\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"77991575-fec4-4cad-ab1e-8e66566bf6eb\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab3\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"357f011c-74a8-4835-8903-15ed89603318\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"af0b344b-4335-442a-b97b-fd2c0118e31d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"4ca6e45d-7001-4ebc-83b8-91744a90017e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab6\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"df0eb2ac-4e77-48f5-9ab9-a7cc8efed9ed\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Hub and spoke\",\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\": \"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\": \"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\": \"{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\": \"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\": \"{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\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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/en-us/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 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\": \"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\": \"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\": \"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\": \"{Query22Stats:$.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\": \"{Query22Stats:$.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\": \"## PaaS\"\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\": \"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\": \"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\": \"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\": \"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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab2title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab2Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/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\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.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\": \"## App delivery\"\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\": \"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\": \"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\": \"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\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{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\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{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\": \"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\": \"## Hybrid\"\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\": \"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\": \"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\": \"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\": \"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 \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab5title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab5Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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\": \"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\": \"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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"## Hub and spoke\"\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\": \"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\": \"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\": \"cab5a7f3-2b73-4e5a-bc10-15dc0df178a6\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"baf36c4b-1078-4d2f-a122-b3942f69cb4c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab1\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"151c633c-4688-4c04-9884-744b07401897\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"01f08a50-0cf6-4f07-ba93-4cb28d81ebde\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"93850e40-f0c4-4d0d-8639-77efd2956691\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d7c73b99-2f75-4ca9-b428-1260b1bd1ed2\",\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\": \"77b08c0e-f06a-4bee-b3ef-9ddbaf939806\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d14c617f-4985-4409-87ac-3ea075746c12\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\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\": 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\": \"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 \"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\": \"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\": \"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\": 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\": \"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 \"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\": \"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\": \"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\": 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 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\": \"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\": \"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\": \"{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\": \"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\": \"{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\": \"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\": \"## Hybrid\"\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\": \"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\": \"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\": \"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\": \"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 \"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\": \"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\": \"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\": 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\": \"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\": \"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 \"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\": \"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 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\": 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\": \"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 \"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\": \"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\": \"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_workbook.json b/workbooks/alz_checklist.en_network_workbook.json index b2f4cf18c..5cabb9a8f 100644 --- a/workbooks/alz_checklist.en_network_workbook.json +++ b/workbooks/alz_checklist.en_network_workbook.json @@ -70,75 +70,75 @@ "style": "tabs", "links": [ { - "id": "93599de3-c584-41d7-b47e-bb8e16c43f38", + "id": "39060c49-25f1-41d5-942e-bef8b40dce49", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "IP plan", "subTarget": "tab0", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "35fec13f-3d43-41aa-ae44-ec96aaf4b604", + "id": "5b2eecdd-b186-46bf-a62e-3cd73f0fd78c", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "PaaS", "subTarget": "tab1", - "preText": "Internet", + "preText": "PaaS", "style": "primary" }, { - "id": "6a06265f-0a05-4f9c-99d1-0e6fb62775b5", + "id": "b931979a-cd2c-48a2-ae9a-f73403c3c6e7", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "Segmentation", "subTarget": "tab2", - "preText": "Virtual WAN", + "preText": "Segmentation", "style": "primary" }, { - "id": "ba968ede-54a5-4825-b04b-508afa2b315e", + "id": "1793e051-c823-4b19-8e31-187b9a5812df", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "App delivery", "subTarget": "tab3", - "preText": "IP plan", + "preText": "App delivery", "style": "primary" }, { - "id": "ab6c6d6e-22d3-49c5-b35b-9f60b837a10f", + "id": "3dbe7f77-9c46-4559-9d28-552a277059ab", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery", + "linkLabel": "Hybrid", "subTarget": "tab4", - "preText": "App delivery", + "preText": "Hybrid", "style": "primary" }, { - "id": "e1664f50-80e1-4b20-b8d8-dcb85ebd5510", + "id": "d49c7dbf-70c6-47cc-97eb-f966b446f984", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "Virtual WAN", "subTarget": "tab5", - "preText": "Hub and spoke", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "befeee22-e583-4da7-80f0-cba7c8cf523a", + "id": "10d6f71d-a8f7-416c-9dbd-330f48007ac5", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "Hub and spoke", "subTarget": "tab6", - "preText": "PaaS", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "268cb6c8-7544-46ac-abf1-35eae644ce26", + "id": "b6a9b34b-1bbc-44d8-9c5f-196fa0e22842", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Internet", "subTarget": "tab7", - "preText": "Hybrid", + "preText": "Internet", "style": "primary" } ] @@ -154,22 +154,22 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## IP plan" }, "name": "tab0title" }, { "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -218,20 +218,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -280,20 +280,42 @@ ] } }, - "name": "query24" + "name": "query15" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab0" + }, + "name": "tab0" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab1title" }, { "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": "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": "querytext25" + "name": "querytext22" }, { "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 = 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", @@ -342,20 +364,42 @@ ] } }, - "name": "query25" + "name": "query22" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab1" + }, + "name": "tab1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Segmentation" + }, + "name": "tab2title" }, { "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 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": "querytext26" + "name": "querytext23" }, { "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 == '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", @@ -404,42 +448,20 @@ ] } }, - "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": "## Internet" - }, - "name": "tab1title" + "name": "query23" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) 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": "querytext16" + "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 == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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", @@ -488,20 +510,20 @@ ] } }, - "name": "query16" + "name": "query24" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) 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": "querytext17" + "name": "querytext25" }, { "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/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", @@ -550,20 +572,20 @@ ] } }, - "name": "query17" + "name": "query25" }, { "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": "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": "querytext18" + "name": "querytext26" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,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", @@ -612,20 +634,42 @@ ] } }, - "name": "query18" + "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": "## App delivery" + }, + "name": "tab3title" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Ensure 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": "querytext19" + "name": "querytext0" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -674,20 +718,20 @@ ] } }, - "name": "query19" + "name": "query0" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "Ensure 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": "querytext20" + "name": "querytext1" }, { "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/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -736,20 +780,20 @@ ] } }, - "name": "query20" + "name": "query1" }, { "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": "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": "querytext21" + "name": "querytext2" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -798,42 +842,20 @@ ] } }, - "name": "query21" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab1" - }, - "name": "tab1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Virtual WAN" - }, - "name": "tab2title" + "name": "query2" }, { "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": "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." }, - "name": "querytext27" + "name": "querytext3" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -882,42 +904,20 @@ ] } }, - "name": "query27" - } - ] - }, - "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": "query3" }, { "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": "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": "querytext14" + "name": "querytext4" }, { "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/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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -966,20 +966,42 @@ ] } }, - "name": "query14" + "name": "query4" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab3" + }, + "name": "tab3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Hybrid" + }, + "name": "tab4title" }, { "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 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": "querytext15" + "name": "querytext9" }, { "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' 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", @@ -1028,42 +1050,20 @@ ] } }, - "name": "query15" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## App delivery" - }, - "name": "tab4title" + "name": "query9" }, { "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." + "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": "querytext0" + "name": "querytext10" }, { "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", + "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", @@ -1112,20 +1112,20 @@ ] } }, - "name": "query0" + "name": "query10" }, { "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." + "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": "querytext1" + "name": "querytext11" }, { "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", + "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", @@ -1174,20 +1174,20 @@ ] } }, - "name": "query1" + "name": "query11" }, { "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": "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": "querytext2" + "name": "querytext12" }, { "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/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", @@ -1236,20 +1236,20 @@ ] } }, - "name": "query2" + "name": "query12" }, { "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": "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": "querytext3" + "name": "querytext13" }, { "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' | 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", @@ -1298,20 +1298,42 @@ ] } }, - "name": "query3" + "name": "query13" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Virtual WAN" + }, + "name": "tab5title" }, { "type": 1, "content": { - "json": "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": "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": "querytext4" + "name": "querytext27" }, { "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/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", @@ -1360,16 +1382,16 @@ ] } }, - "name": "query4" + "name": "query27" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab5" }, - "name": "tab4" + "name": "tab5" }, { "type": 12, @@ -1382,7 +1404,7 @@ "content": { "json": "## Hub and spoke" }, - "name": "tab5title" + "name": "tab6title" }, { "type": 1, @@ -1637,9 +1659,9 @@ "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab6" }, - "name": "tab5" + "name": "tab6" }, { "type": 12, @@ -1650,22 +1672,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Internet" }, - "name": "tab6title" + "name": "tab7title" }, { "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 Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext22" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -1714,42 +1736,20 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab6" - }, - "name": "tab6" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hybrid" - }, - "name": "tab7title" + "name": "query16" }, { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext9" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1798,20 +1798,20 @@ ] } }, - "name": "query9" + "name": "query17" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext10" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1860,20 +1860,20 @@ ] } }, - "name": "query10" + "name": "query18" }, { "type": 1, "content": { - "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext11" + "name": "querytext19" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1922,20 +1922,20 @@ ] } }, - "name": "query11" + "name": "query19" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext12" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1984,20 +1984,20 @@ ] } }, - "name": "query12" + "name": "query20" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, - "name": "querytext13" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2046,7 +2046,7 @@ ] } }, - "name": "query13" + "name": "query21" } ] }, diff --git a/workbooks/alz_checklist.en_network_workbook_template.json b/workbooks/alz_checklist.en_network_workbook_template.json index bd81c7c29..0463816f4 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\": \"93599de3-c584-41d7-b47e-bb8e16c43f38\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"35fec13f-3d43-41aa-ae44-ec96aaf4b604\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6a06265f-0a05-4f9c-99d1-0e6fb62775b5\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"ba968ede-54a5-4825-b04b-508afa2b315e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"ab6c6d6e-22d3-49c5-b35b-9f60b837a10f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e1664f50-80e1-4b20-b8d8-dcb85ebd5510\",\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\": \"befeee22-e583-4da7-80f0-cba7c8cf523a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab6\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"268cb6c8-7544-46ac-abf1-35eae644ce26\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\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\": \"## 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\": \"## Internet\"\n },\n \"name\": \"tab1title\"\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/en-us/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 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\": \"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\": \"## Virtual WAN\"\n },\n \"name\": \"tab2title\"\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\": \"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\": \"## 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\": 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\": \"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\": \"## Hub and spoke\"\n },\n \"name\": \"tab5title\"\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\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"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\": \"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\": 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\": \"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\": \"39060c49-25f1-41d5-942e-bef8b40dce49\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab0\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5b2eecdd-b186-46bf-a62e-3cd73f0fd78c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab1\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b931979a-cd2c-48a2-ae9a-f73403c3c6e7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"1793e051-c823-4b19-8e31-187b9a5812df\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab3\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3dbe7f77-9c46-4559-9d28-552a277059ab\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d49c7dbf-70c6-47cc-97eb-f966b446f984\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"10d6f71d-a8f7-416c-9dbd-330f48007ac5\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b6a9b34b-1bbc-44d8-9c5f-196fa0e22842\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab0title\"\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\": \"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\": \"## PaaS\"\n },\n \"name\": \"tab1title\"\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\": \"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\": \"## App delivery\"\n },\n \"name\": \"tab3title\"\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\": \"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\": \"## Hybrid\"\n },\n \"name\": \"tab4title\"\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\": \"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\": 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\": \"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\": \"## Hub and spoke\"\n },\n \"name\": \"tab6title\"\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\": \"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\": \"## Internet\"\n },\n \"name\": \"tab7title\"\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 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\": \"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_workbook.json b/workbooks/alz_checklist.en_workbook.json index e507041a3..95f0ea8ba 100644 --- a/workbooks/alz_checklist.en_workbook.json +++ b/workbooks/alz_checklist.en_workbook.json @@ -70,7 +70,7 @@ "style": "tabs", "links": [ { - "id": "a46deeb8-8a27-4f42-b53f-2e9320912d32", + "id": "0171fc2e-c94c-4d8c-9d7f-57119317685a", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity", @@ -79,7 +79,7 @@ "style": "primary" }, { - "id": "274c7305-c260-43d3-8925-9727cfd08ef2", + "id": "a0f00618-1c51-4904-803b-a9da69403a5b", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Security", @@ -88,7 +88,7 @@ "style": "primary" }, { - "id": "1272812e-c6d9-40b2-930f-d855d1bbdbf2", + "id": "0fecdb0b-283a-4f08-9d4e-55f763536d8c", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Resource Organization", @@ -1108,7 +1108,7 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) 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": "querytext16" }, diff --git a/workbooks/alz_checklist.en_workbook_template.json b/workbooks/alz_checklist.en_workbook_template.json index aa53137c8..4a54f5ef6 100644 --- a/workbooks/alz_checklist.en_workbook_template.json +++ b/workbooks/alz_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 Landing Zone 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\": \"a46deeb8-8a27-4f42-b53f-2e9320912d32\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"274c7305-c260-43d3-8925-9727cfd08ef2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"1272812e-c6d9-40b2-930f-d855d1bbdbf2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Resource Organization\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Resource Organization\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"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 \"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 \"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 \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/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 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 \"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 \"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 \"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\": \"## Security\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext32\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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) | 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\": \"query32\"\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\": \"## Resource Organization\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than four levels. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext28\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 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\": \"query28\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext29\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query29\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext30\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 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\": \"query30\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext31\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query31\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\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\\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\": \"0171fc2e-c94c-4d8c-9d7f-57119317685a\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a0f00618-1c51-4904-803b-a9da69403a5b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0fecdb0b-283a-4f08-9d4e-55f763536d8c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Resource Organization\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Resource Organization\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n },\n {\n \"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 \"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 \"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 \"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 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 \"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 \"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 \"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\": \"## Security\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext32\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"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) | 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\": \"query32\"\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\": \"## Resource Organization\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than four levels. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext28\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 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\": \"query28\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext29\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query29\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext30\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 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\": \"query30\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext31\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, 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\": \"query31\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\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')]"