From 0cd1ec743d57a71659cdb7d825ec5e30471746f8 Mon Sep 17 00:00:00 2001 From: erjosito Date: Wed, 4 Oct 2023 10:02:25 +0000 Subject: [PATCH] [create-pull-request] automated change --- checklists/sap_checklist.en.json | 8 +- checklists/sap_checklist.es.json | 91 +- checklists/sap_checklist.ja.json | 91 +- checklists/sap_checklist.ko.json | 89 +- checklists/sap_checklist.pt.json | 91 +- spreadsheet/macrofree/sap_checklist.en.xlsx | Bin 29783 -> 30101 bytes spreadsheet/macrofree/sap_checklist.es.xlsx | Bin 30563 -> 30917 bytes spreadsheet/macrofree/sap_checklist.ja.xlsx | Bin 32655 -> 33022 bytes spreadsheet/macrofree/sap_checklist.ko.xlsx | Bin 31938 -> 32259 bytes spreadsheet/macrofree/sap_checklist.pt.xlsx | Bin 30681 -> 31036 bytes .../alz_checklist.en_network_counters.json | 500 +++--- ...hecklist.en_network_counters_template.json | 2 +- .../alz_checklist.en_network_tabcounters.json | 1454 ++++++++--------- ...klist.en_network_tabcounters_template.json | 2 +- .../alz_checklist.en_network_workbook.json | 468 +++--- ...hecklist.en_network_workbook_template.json | 2 +- 16 files changed, 1401 insertions(+), 1397 deletions(-) diff --git a/checklists/sap_checklist.en.json b/checklists/sap_checklist.en.json index 2e4683847..3d894111e 100644 --- a/checklists/sap_checklist.en.json +++ b/checklists/sap_checklist.en.json @@ -267,7 +267,7 @@ "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", "severity": "Low", "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity" - }, + }, { "category": "Management Group and Subscriptions", "subcategory": "Subscriptions", @@ -275,7 +275,7 @@ "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", "severity": "High", "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal" - }, + }, { "category": "Management Group and Subscriptions", "subcategory": "Subscriptions", @@ -293,7 +293,7 @@ "severity": "Medium", "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/", "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization" - }, + }, { "category": "Management and Monitoring", "subcategory": "Monitoring", @@ -749,4 +749,4 @@ "state": "Preview", "timestamp": "October 04, 2023" } -} +} \ No newline at end of file diff --git a/checklists/sap_checklist.es.json b/checklists/sap_checklist.es.json index 45da5ae51..e4e553cf5 100644 --- a/checklists/sap_checklist.es.json +++ b/checklists/sap_checklist.es.json @@ -120,25 +120,25 @@ { "category": "Identidad y acceso", "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", - "link": "https://learn.microsoft.com/en-us/azure/well-architected/sap/design-areas/security", + "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", "severity": "Alto", "subcategory": "Identidad", "text": "Aplicar un modelo RBAC para grupos de administración, suscripciones, grupos de recursos y recursos", - "training": "https://learn.microsoft.com/en-us/training/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "Identidad y acceso", "guid": "45911475-e39e-4530-accc-d979366bcda2", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "Medio", "subcategory": "Identidad", "text": "Aplicar la propagación del principio para reenviar la identidad desde la aplicación en la nube de SAP a SAP local (incluida IaaS) a través del conector de nube", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" }, { "category": "Identidad y acceso", "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "Medio", "subcategory": "Identidad", "text": "Implemente SSO en aplicaciones SaaS de SAP como SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics y SAP C4C con Azure AD mediante SAML." @@ -146,11 +146,11 @@ { "category": "Identidad y acceso", "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "Medio", "subcategory": "Identidad", "text": "Implemente SSO en aplicaciones web basadas en SAP NetWeaver como SAP Fiori y SAP Web GUI mediante SAML.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "Identidad y acceso", @@ -158,16 +158,16 @@ "severity": "Medio", "subcategory": "Identidad", "text": "Implemente SSO en aplicaciones web basadas en SAP NetWeaver como SAP Fiori y SAP Web GUI mediante SAML.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" }, { "category": "Identidad y acceso", "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "Medio", "subcategory": "Identidad", "text": "Puede implementar SSO en SAP GUI mediante SAP NetWeaver SSO o una solución de socio.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "Identidad y acceso", @@ -175,7 +175,7 @@ "severity": "Medio", "subcategory": "Identidad", "text": "Para SSO para SAP GUI y acceso al navegador web, implemente SNC – Kerberos/SPNEGO (mecanismo de negociación GSSAPI simple y protegido) debido a su facilidad de configuración y mantenimiento. Para SSO con certificados de cliente X.509, considere SAP Secure Login Server, que es un componente de la solución SAP SSO.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" }, { "category": "Identidad y acceso", @@ -188,7 +188,7 @@ { "category": "Identidad y acceso", "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", "severity": "Medio", "subcategory": "Identidad", "text": "Implemente SSO mediante OAuth para SAP NetWeaver para permitir que aplicaciones personalizadas o de terceros accedan a los servicios OData de SAP NetWeaver." @@ -196,7 +196,7 @@ { "category": "Identidad y acceso", "guid": "a747c350-8d4c-449c-93af-393dbca77c48", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/saphana-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", "severity": "Medio", "subcategory": "Identidad", "text": "Implementar SSO en SAP HANA" @@ -204,7 +204,7 @@ { "category": "Identidad y acceso", "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", - "link": "https://learn.microsoft.com/en-us/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", "severity": "Medio", "subcategory": "Identidad", "text": "Considere Azure AD como un proveedor de identidades para sistemas SAP hospedados en RISE. Para obtener más información, consulte Integración del servicio con Azure AD." @@ -220,7 +220,7 @@ { "category": "Identidad y acceso", "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", "severity": "Medio", "subcategory": "Identidad", "text": "Si usa servicios BTP de SAP o soluciones SaaS que requieren SAP Identity Authentication Service (IAS), considere la posibilidad de implementar SSO entre SAP Cloud Identity Authentication Services y Azure AD para acceder a esos servicios de SAP. Esta integración permite que SAP IAS actúe como proveedor de identidades proxy y reenvíe las solicitudes de autenticación a Azure AD como almacén de usuarios central y proveedor de identidades." @@ -228,7 +228,7 @@ { "category": "Identidad y acceso", "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", "severity": "Medio", "subcategory": "Identidad", "text": "Implementar SSO en SAP BTP" @@ -244,71 +244,72 @@ { "category": "Grupo de administración y suscripciones", "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "Medio", "subcategory": "Suscripciones", "text": "aplicar directivas de grupo de administración existentes a suscripciones de SAP", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" }, { "category": "Grupo de administración y suscripciones", "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", - "severity": "Medio", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "Alto", "subcategory": "Suscripciones", - "text": "Permitir que las aplicaciones estén estrechamente acopladas en la misma suscripción de SAP para evitar una complejidad adicional de enrutamiento y administración", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "text": "Integre aplicaciones estrechamente acopladas en la misma suscripción de SAP para evitar una complejidad adicional de enrutamiento y administración", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" }, { "category": "Grupo de administración y suscripciones", "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medio", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "Alto", "subcategory": "Suscripciones", "text": "Aproveche la suscripción como unidad de escala y escalando nuestros recursos, considere implementar la suscripción por entorno, por ejemplo. Sandbox, no prod, prod ", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" }, { "category": "Grupo de administración y suscripciones", "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medio", + "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", + "severity": "Alto", "subcategory": "Suscripciones", - "text": "Garantice el aumento de la cuota como parte del aprovisionamiento de suscripciones (por ejemplo, el total de núcleos de VM disponibles dentro de una suscripción).", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "Garantizar el aumento de la cuota como parte del aprovisionamiento de suscripciones (por ejemplo, el total de núcleos de VM disponibles dentro de una suscripción)", + "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" }, { "category": "Grupo de administración y suscripciones", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medio", + "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", + "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", + "severity": "Bajo", "subcategory": "Suscripciones", - "text": "Asegúrese de que los servicios y características requeridos estén disponibles dentro de las regiones de implementación elegidas, por ejemplo. ANF, zona, etc.", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "La API de cuota es una API de REST que puede usar para ver y administrar cuotas para servicios de Azure. Considere usarlo si es necesario." }, { "category": "Grupo de administración y suscripciones", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medio", + "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", + "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", + "severity": "Alto", "subcategory": "Suscripciones", - "text": "Aproveche la etiqueta de recursos de Azure para la categorización de costos y la agrupación de recursos (BillTo, Departamento (o unidad de negocio), Entorno (producción, etapa, desarrollo), Nivel (nivel web, nivel de aplicación), propietario de la aplicación, nombre del proyecto)" + "text": "Si se implementa en una zona de disponibilidad, asegúrese de que la implementación de la zona de la máquina virtual esté disponible una vez que se haya aprobado la cuota. Envíe una solicitud de soporte con la suscripción, la serie de máquinas virtuales, el número de CPU y la zona de disponibilidad requerida." }, { "category": "Grupo de administración y suscripciones", - "guid": "7d474317-6c8b-4cbf-95bb-e609d8a03e97", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Medio", + "guid": "e6e20617-3686-4af4-9791-f8935ada4332", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", + "severity": "Alto", "subcategory": "Suscripciones", - "text": " " + "text": "Asegúrese de que los servicios y características requeridos estén disponibles dentro de las regiones de implementación elegidas, por ejemplo. ANF, zona, etc.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" }, { "category": "Grupo de administración y suscripciones", - "guid": "778424d6-1678-45d6-ba96-c96ad88518f4", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", "severity": "Medio", "subcategory": "Suscripciones", - "text": " " + "text": "Aproveche la etiqueta de recursos de Azure para la categorización de costos y la agrupación de recursos (BillTo, Departamento (o unidad de negocio), Entorno (producción, etapa, desarrollo), Nivel (nivel web, nivel de aplicación), propietario de la aplicación, nombre del proyecto)", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "Gestión y Monitoreo", diff --git a/checklists/sap_checklist.ja.json b/checklists/sap_checklist.ja.json index 25bea90ac..b49d837fb 100644 --- a/checklists/sap_checklist.ja.json +++ b/checklists/sap_checklist.ja.json @@ -120,25 +120,25 @@ { "category": "ID とアクセス", "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", - "link": "https://learn.microsoft.com/en-us/azure/well-architected/sap/design-areas/security", + "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", "severity": "高い", "subcategory": "同一性", "text": "管理グループ、サブスクリプション、リソース グループ、およびリソースに対して RBAC モデルを適用する", - "training": "https://learn.microsoft.com/en-us/training/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "ID とアクセス", "guid": "45911475-e39e-4530-accc-d979366bcda2", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "中程度", "subcategory": "同一性", "text": "クラウド コネクタを介して SAP クラウド アプリケーションからオンプレミスの SAP (IaaS を含む) に ID を転送するための原則の伝達を適用する", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" }, { "category": "ID とアクセス", "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "中程度", "subcategory": "同一性", "text": "SAML を使用して、SAP Analytics Cloud、SAP Cloud Platform、Business by Design、SAP Qualtrics、SAP C4C with Azure AD などの SAP SaaS アプリケーションへの SSO を実装します。" @@ -146,11 +146,11 @@ { "category": "ID とアクセス", "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "中程度", "subcategory": "同一性", "text": "SAML を使用して、SAP Fiori や SAP Web GUI などの SAP NetWeaver ベースの Web アプリケーションへの SSO を実装します。", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "ID とアクセス", @@ -158,16 +158,16 @@ "severity": "中程度", "subcategory": "同一性", "text": "SAML を使用して、SAP Fiori や SAP Web GUI などの SAP NetWeaver ベースの Web アプリケーションへの SSO を実装します。", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" }, { "category": "ID とアクセス", "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "中程度", "subcategory": "同一性", "text": "SAP GUI への SSO は、SAP NetWeaver SSO またはパートナーソリューションを使用して実装できます。", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "ID とアクセス", @@ -175,7 +175,7 @@ "severity": "中程度", "subcategory": "同一性", "text": "SAP GUI および Web ブラウザー・アクセス用の SSO の場合、構成と保守が容易であるため、SNC – Kerberos/SPNEGO (単純で保護された GSSAPI ネゴシエーション・メカニズム) を実装します。X.509 クライアント証明書を使用した SSO の場合は、SAP SSO ソリューションのコンポーネントである SAP セキュア ログイン サーバーを検討してください。", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" }, { "category": "ID とアクセス", @@ -188,7 +188,7 @@ { "category": "ID とアクセス", "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", "severity": "中程度", "subcategory": "同一性", "text": "OAuth for SAP NetWeaver を使用して SSO を実装し、サードパーティまたはカスタムアプリケーションが SAP NetWeaver OData サービスにアクセスできるようにします。" @@ -196,7 +196,7 @@ { "category": "ID とアクセス", "guid": "a747c350-8d4c-449c-93af-393dbca77c48", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/saphana-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", "severity": "中程度", "subcategory": "同一性", "text": "SAP HANA への SSO の実装" @@ -204,7 +204,7 @@ { "category": "ID とアクセス", "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", - "link": "https://learn.microsoft.com/en-us/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", "severity": "中程度", "subcategory": "同一性", "text": "Azure AD を RISE でホストされている SAP システムの ID プロバイダーと考えてください。詳細については、「サービスと Azure AD の統合」を参照してください。" @@ -220,7 +220,7 @@ { "category": "ID とアクセス", "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", "severity": "中程度", "subcategory": "同一性", "text": "SAP ID 認証サービス (IAS) を必要とする SAP BTP サービスまたは SaaS ソリューションを使用している場合は、SAP Cloud ID 認証サービスと Azure AD の間に SSO を実装して、これらの SAP サービスにアクセスすることを検討してください。この統合により、SAP IAS はプロキシ ID プロバイダーとして機能し、認証要求を中央ユーザー ストアおよび ID プロバイダーとして Azure AD に転送できます。" @@ -228,7 +228,7 @@ { "category": "ID とアクセス", "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", "severity": "中程度", "subcategory": "同一性", "text": "SAP BTP への SSO の実装" @@ -244,71 +244,72 @@ { "category": "管理グループとサブスクリプション", "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "中程度", "subcategory": "サブスクリプション", "text": "既存の管理グループ ポリシーを SAP サブスクリプションに適用する", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" }, { "category": "管理グループとサブスクリプション", "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", - "severity": "中程度", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "高い", "subcategory": "サブスクリプション", - "text": "緊密に結合されたアプリケーションを同じSAPサブスクリプションに統合して、ルーティングと管理の複雑さを回避", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "text": "密結合アプリケーションを同じSAPサブスクリプションに統合して、ルーティングと管理の複雑さを回避", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" }, { "category": "管理グループとサブスクリプション", "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "中程度", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "高い", "subcategory": "サブスクリプション", "text": "サブスクリプションをスケール ユニットとして活用し、リソースをスケーリングする場合は、環境ごとにサブスクリプションをデプロイすることを検討してください。サンドボックス、非製品、製品", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" }, { "category": "管理グループとサブスクリプション", "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "中程度", + "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", + "severity": "高い", "subcategory": "サブスクリプション", - "text": "サブスクリプションのプロビジョニングの一環としてクォータを増やします (サブスクリプション内で使用可能な VM コアの合計など)。", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "サブスクリプションのプロビジョニングの一環としてクォータを増やす (サブスクリプション内で使用可能な VM コアの合計など)", + "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" }, { "category": "管理グループとサブスクリプション", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "中程度", + "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", + "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", + "severity": "低い", "subcategory": "サブスクリプション", - "text": "必要なサービスと機能が、選択した展開リージョン内で利用可能であることを確認します。ANF、ゾーンなど", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "クォータ API は、Azure サービスのクォータを表示および管理するために使用できる REST API です。必要に応じて使用を検討してください。" }, { "category": "管理グループとサブスクリプション", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "中程度", + "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", + "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", + "severity": "高い", "subcategory": "サブスクリプション", - "text": "Azure リソース タグを活用して、コストの分類とリソースのグループ化 (請求先、部門 (または部署)、環境 (運用、ステージ、開発)、層 (Web 層、アプリケーション層)、アプリケーション所有者、プロジェクト名)" + "text": "可用性ゾーンにデプロイする場合は、クォータが承認された後に VM のゾーン デプロイが使用可能であることを確認します。サブスクリプション、VM シリーズ、必要な CPU の数、可用性ゾーンを含むサポート リクエストを送信します。" }, { "category": "管理グループとサブスクリプション", - "guid": "7d474317-6c8b-4cbf-95bb-e609d8a03e97", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "中程度", + "guid": "e6e20617-3686-4af4-9791-f8935ada4332", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", + "severity": "高い", "subcategory": "サブスクリプション", - "text": " " + "text": "必要なサービスと機能が、選択した展開リージョン内で利用可能であることを確認します。ANF、ゾーンなど", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" }, { "category": "管理グループとサブスクリプション", - "guid": "778424d6-1678-45d6-ba96-c96ad88518f4", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", "severity": "中程度", "subcategory": "サブスクリプション", - "text": " " + "text": "Azure リソース タグを活用して、コストの分類とリソースのグループ化 (請求先、部門 (または部署)、環境 (運用、ステージ、開発)、層 (Web 層、アプリケーション層)、アプリケーション所有者、プロジェクト名)", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "管理と監視", diff --git a/checklists/sap_checklist.ko.json b/checklists/sap_checklist.ko.json index 88a6a8e5c..91d81cd34 100644 --- a/checklists/sap_checklist.ko.json +++ b/checklists/sap_checklist.ko.json @@ -120,25 +120,25 @@ { "category": "ID 및 액세스", "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", - "link": "https://learn.microsoft.com/en-us/azure/well-architected/sap/design-areas/security", + "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", "severity": "높다", "subcategory": "신원", "text": "관리 그룹, 구독, 리소스 그룹 및 리소스에 대한 RBAC 모델 적용Enforce a RBAC model for management groups, subscriptions, resource groups and resources", - "training": "https://learn.microsoft.com/en-us/training/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "ID 및 액세스", "guid": "45911475-e39e-4530-accc-d979366bcda2", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "보통", "subcategory": "신원", "text": "클라우드 커넥터를 통해 SAP 클라우드 애플리케이션에서 SAP 온-프레미스(IaaS 포함)로 ID를 전달하기 위한 원칙 전파 적용Enforce Principle propagation for forwarding the identity from SAP cloud application to SAP on-premises (including IaaS) through cloud connector", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" }, { "category": "ID 및 액세스", "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "보통", "subcategory": "신원", "text": "SAML을 사용하여 Azure AD에서 SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics 및 SAP C4C와 같은 SAP SaaS 애플리케이션에 대한 SSO를 구현합니다." @@ -146,11 +146,11 @@ { "category": "ID 및 액세스", "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "보통", "subcategory": "신원", "text": "SAML을 사용하여 SAP NetWeaver 기반 웹 애플리케이션(예: SAP Fiori 및 SAP Web GUI)에 대한 SSO를 구현합니다.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "ID 및 액세스", @@ -158,16 +158,16 @@ "severity": "보통", "subcategory": "신원", "text": "SAML을 사용하여 SAP NetWeaver 기반 웹 애플리케이션(예: SAP Fiori 및 SAP Web GUI)에 대한 SSO를 구현합니다.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" }, { "category": "ID 및 액세스", "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "보통", "subcategory": "신원", "text": "SAP NetWeaver SSO 또는 파트너 솔루션을 사용하여 SAP GUI에 대한 SSO를 구현할 수 있습니다.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "ID 및 액세스", @@ -175,7 +175,7 @@ "severity": "보통", "subcategory": "신원", "text": "SAP GUI 및 웹 브라우저 액세스에 대한 SSO의 경우 구성 및 유지 관리가 용이하기 때문에 SNC – Kerberos/SPNEGO(단순하고 보호된 GSSAPI 협상 메커니즘)를 구현합니다. X.509 클라이언트 인증서를 사용하는 SSO의 경우 SAP SSO 솔루션의 구성 요소인 SAP 보안 로그인 서버를 사용하는 것이 좋습니다.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" }, { "category": "ID 및 액세스", @@ -188,7 +188,7 @@ { "category": "ID 및 액세스", "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", "severity": "보통", "subcategory": "신원", "text": "OAuth for SAP NetWeaver를 사용하여 SSO를 구현하면 타사 또는 사용자 지정 애플리케이션이 SAP NetWeaver OData 서비스에 액세스할 수 있습니다." @@ -196,7 +196,7 @@ { "category": "ID 및 액세스", "guid": "a747c350-8d4c-449c-93af-393dbca77c48", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/saphana-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", "severity": "보통", "subcategory": "신원", "text": "SAP HANA에 대한 SSO 구현" @@ -204,7 +204,7 @@ { "category": "ID 및 액세스", "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", - "link": "https://learn.microsoft.com/en-us/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", "severity": "보통", "subcategory": "신원", "text": "RISE에서 호스트되는 SAP 시스템에 대한 ID 공급자인 Azure AD를 고려합니다. 자세한 내용은 Azure AD와 서비스 통합을 참조하세요." @@ -220,7 +220,7 @@ { "category": "ID 및 액세스", "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", "severity": "보통", "subcategory": "신원", "text": "SAP IAS(Identity Authentication Service)가 필요한 SAP BTP 서비스 또는 SaaS 솔루션을 사용하는 경우 SAP Cloud Identity Authentication Services와 Azure AD 간에 SSO를 구현하여 해당 SAP 서비스에 액세스하는 것이 좋습니다. 이 통합을 통해 SAP IAS는 프록시 ID 공급자 역할을 하고 중앙 사용자 저장소 및 ID 공급자인 Azure AD에 인증 요청을 전달할 수 있습니다." @@ -228,7 +228,7 @@ { "category": "ID 및 액세스", "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", "severity": "보통", "subcategory": "신원", "text": "SAP BTP에 대한 SSO 구현" @@ -244,71 +244,72 @@ { "category": "관리 그룹 및 구독Management Group and Subscriptions", "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "보통", "subcategory": "구독", "text": "SAP 구독에 기존 관리 그룹 정책 적용Enforce existing Management Group policies to SAP Subscriptions", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", - "severity": "보통", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "높다", "subcategory": "구독", - "text": "밀접하게 결합된 애플리케이션을 동일한 SAP 서브스크립션으로 통합하여 추가적인 라우팅 및 관리 복잡성을 방지합니다.", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "text": "긴밀하게 결합된 애플리케이션을 동일한 SAP 구독에 통합하여 추가적인 라우팅 및 관리 복잡성을 방지합니다.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "보통", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "높다", "subcategory": "구독", "text": "구독을 배율 단위로 활용하고 리소스를 확장하려면 환경별로 구독을 배포하는 것이 좋습니다. 샌드박스, 비프로덕션, 프로덕션(prod) ", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "보통", + "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", + "severity": "높다", "subcategory": "구독", "text": "구독 프로비저닝의 일부로 할당량 증가를 확인합니다(예: 구독 내에서 사용 가능한 총 VM 코어).", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "보통", + "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", + "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", + "severity": "낮다", "subcategory": "구독", - "text": "필요한 서비스 및 기능을 선택한 배포 지역 내에서 사용할 수 있는지 확인합니다. ANF, 구역 등", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "할당량 API는 Azure 서비스에 대한 할당량을 보고 관리하는 데 사용할 수 있는 REST API입니다. 필요한 경우 사용을 고려하십시오." }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "보통", + "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", + "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", + "severity": "높다", "subcategory": "구독", - "text": "비용 분류 및 리소스 그룹화(: BillTo, 부서(또는 사업부), 환경(프로덕션, 스테이지, 개발), 계층(웹 계층, 애플리케이션 계층), 애플리케이션 소유자, ProjectName)에 Azure 리소스 태그 활용" + "text": "가용성 영역에 배포하는 경우 할당량이 승인되면 VM의 영역 배포를 사용할 수 있는지 확인합니다. 필요한 구독, VM 시리즈, CPU 수 및 가용성 영역을 사용하여 지원 요청을 제출합니다." }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", - "guid": "7d474317-6c8b-4cbf-95bb-e609d8a03e97", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "보통", + "guid": "e6e20617-3686-4af4-9791-f8935ada4332", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", + "severity": "높다", "subcategory": "구독", - "text": " " + "text": "필요한 서비스 및 기능을 선택한 배포 지역 내에서 사용할 수 있는지 확인합니다. ANF, 구역 등", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" }, { "category": "관리 그룹 및 구독Management Group and Subscriptions", - "guid": "778424d6-1678-45d6-ba96-c96ad88518f4", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", "severity": "보통", "subcategory": "구독", - "text": " " + "text": "비용 분류 및 리소스 그룹화(: BillTo, 부서(또는 사업부), 환경(프로덕션, 스테이지, 개발), 계층(웹 계층, 애플리케이션 계층), 애플리케이션 소유자, ProjectName)에 Azure 리소스 태그 활용", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "관리 및 모니터링", diff --git a/checklists/sap_checklist.pt.json b/checklists/sap_checklist.pt.json index a3e1ca3f7..df2d9d531 100644 --- a/checklists/sap_checklist.pt.json +++ b/checklists/sap_checklist.pt.json @@ -120,25 +120,25 @@ { "category": "Identidade e Acesso", "guid": "fda1dbf3-dc95-4d48-a7c7-91dca0f6c565", - "link": "https://learn.microsoft.com/en-us/azure/well-architected/sap/design-areas/security", + "link": "https://learn.microsoft.com/azure/well-architected/sap/design-areas/security", "severity": "Alto", "subcategory": "Identidade", "text": "Impor um modelo RBAC para grupos de gerenciamento, assinaturas, grupos de recursos e recursos", - "training": "https://learn.microsoft.com/en-us/training/paths/implement-resource-mgmt-security/" + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "Identidade e Acesso", "guid": "45911475-e39e-4530-accc-d979366bcda2", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "Média", "subcategory": "Identidade", "text": "Aplicar a propagação do princípio para encaminhar a identidade do aplicativo de nuvem SAP para o SAP local (incluindo IaaS) por meio do conector de nuvem", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/2-explore-azure-virtual-machine-auth-access-control" }, { "category": "Identidade e Acesso", "guid": "750ab1ab-039d-495d-94c7-c8929cb107d5", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", + "link": "https://learn.microsoft.com/azure/active-directory/fundamentals/scenario-azure-first-sap-identity-integration", "severity": "Média", "subcategory": "Identidade", "text": "Implemente SSO em aplicativos SAP SaaS como SAP Analytics Cloud, SAP Cloud Platform, Business by design, SAP Qualtrics e SAP C4C com o Azure AD usando SAML." @@ -146,11 +146,11 @@ { "category": "Identidade e Acesso", "guid": "325ae525-ba34-4d46-a5e2-213ace7bb122", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "Média", "subcategory": "Identidade", "text": "Implemente SSO em aplicativos Web baseados no SAP NetWeaver, como SAP Fiori e SAP Web GUI, usando SAML.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "Identidade e Acesso", @@ -158,16 +158,16 @@ "severity": "Média", "subcategory": "Identidade", "text": "Implemente SSO em aplicativos Web baseados no SAP NetWeaver, como SAP Fiori e SAP Web GUI, usando SAML.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/6-exercise-integrate-azure-active-directory-sap-fiori" }, { "category": "Identidade e Acesso", "guid": "f29676ef-0c9c-4c4d-ab21-a55504c0c829", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial", "severity": "Média", "subcategory": "Identidade", "text": "Você pode implementar o SSO para SAP GUI usando o SAP NetWeaver SSO ou uma solução de parceiro.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/8-exercise-integrate-azure-active-directory-sap-netweaver" }, { "category": "Identidade e Acesso", @@ -175,7 +175,7 @@ "severity": "Média", "subcategory": "Identidade", "text": "Para SSO para SAP GUI e acesso ao navegador web, implemente SNC – Kerberos/SPNEGO (mecanismo de negociação GSSAPI simples e protegido) devido à sua facilidade de configuração e manutenção. Para SSO com certificados de cliente X.509, considere o SAP Secure Login Server, que é um componente da solução SAP SSO.", - "training": "https://learn.microsoft.com/en-us/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" + "training": "https://learn.microsoft.com/training/modules/explore-identity-services/9-exercise-integrate-active-directory-sap-single-sign-on" }, { "category": "Identidade e Acesso", @@ -188,7 +188,7 @@ { "category": "Identidade e Acesso", "guid": "16785d6f-a96c-496a-b885-18f482734c88", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-netweaver-tutorial#configure-sap-netweaver-for-oauth", "severity": "Média", "subcategory": "Identidade", "text": "Implemente o SSO usando o OAuth for SAP NetWeaver para permitir que aplicativos de terceiros ou personalizados acessem os serviços OData do SAP NetWeaver." @@ -196,7 +196,7 @@ { "category": "Identidade e Acesso", "guid": "a747c350-8d4c-449c-93af-393dbca77c48", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/saphana-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/saphana-tutorial", "severity": "Média", "subcategory": "Identidade", "text": "Implementar SSO no SAP HANA" @@ -204,7 +204,7 @@ { "category": "Identidade e Acesso", "guid": "c7bae5bf-daf9-4761-9c56-f92891890aa4", - "link": "https://learn.microsoft.com/en-us/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", + "link": "https://learn.microsoft.com/azure/sap/workloads/rise-integration#connectivity-with-sap-rise", "severity": "Média", "subcategory": "Identidade", "text": "Considere o Azure AD um provedor de identidade para sistemas SAP hospedados no RISE. Para obter mais informações, consulte Integrando o serviço ao Azure AD." @@ -220,7 +220,7 @@ { "category": "Identidade e Acesso", "guid": "59921095-4980-4fc1-a5b6-524a5a560c79", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-identity-authentication-tutorial", "severity": "Média", "subcategory": "Identidade", "text": "Se você estiver usando serviços SAP BTP ou soluções SaaS que exigem o SAP Identity Authentication Service (IAS), considere implementar SSO entre o SAP Cloud Identity Authentication Services e o Azure AD para acessar esses serviços SAP. Essa integração permite que o SAP IAS atue como um provedor de identidade de proxy e encaminhe solicitações de autenticação para o Azure AD como o repositório central do usuário e o provedor de identidade." @@ -228,7 +228,7 @@ { "category": "Identidade e Acesso", "guid": "a709c664-317e-41e4-9e34-67d9016a86f4", - "link": "https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", + "link": "https://learn.microsoft.com/azure/active-directory/saas-apps/sap-hana-cloud-platform-tutorial", "severity": "Média", "subcategory": "Identidade", "text": "Implementar SSO no SAP BTP" @@ -244,71 +244,72 @@ { "category": "Grupo de Gerenciamento e Assinaturas", "guid": "6ba28021-4591-4147-9e39-e5309cccd979", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups", "severity": "Média", "subcategory": "Assinaturas", "text": "impor políticas existentes do Grupo de Gerenciamento às assinaturas SAP", - "training": "https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/" + "training": "https://learn.microsoft.com/training/modules/enterprise-scale-organization/4-management-group-subscription-organization" }, { "category": "Grupo de Gerenciamento e Assinaturas", "guid": "366bcda2-750a-4b1a-a039-d95d54c7c892", - "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json", - "severity": "Média", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "Alto", "subcategory": "Assinaturas", - "text": "Implemente aplicativos estreitamente acoplados na mesma assinatura SAP para evitar complexidade adicional de roteamento e gerenciamento", - "training": "https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/" + "text": "Integre aplicativos fortemente acoplados na mesma assinatura SAP para evitar complexidade adicional de roteamento e gerenciamento", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-subscriptions" }, { "category": "Grupo de Gerenciamento e Assinaturas", "guid": "9cb107d5-325a-4e52-9ba3-4d4685e2213a", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Média", + "link": "https://learn.microsoft.com/azure/architecture/guide/sap/sap-whole-landscape", + "severity": "Alto", "subcategory": "Assinaturas", "text": "Aproveite a assinatura como unidade de escala e dimensione nossos recursos, considere implantar a assinatura por ambiente, por exemplo. Sandbox, não-prod, prod ", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "training": "https://learn.microsoft.com/training/modules/configure-subscriptions/?source=recommendations" }, { "category": "Grupo de Gerenciamento e Assinaturas", "guid": "ce7bb122-f7c9-45f0-9e15-4e3aa3592829", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Média", + "link": "https://learn.microsoft.com/azure/quotas/quotas-overview", + "severity": "Alto", "subcategory": "Assinaturas", - "text": "Garanta o aumento da cota como parte do provisionamento de assinatura (por exemplo, total de núcleos de VM disponíveis em uma assinatura).", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "Garantir o aumento da cota como parte do provisionamento de assinatura (por exemplo, total de núcleos de VM disponíveis em uma assinatura)", + "training": "https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits" }, { "category": "Grupo de Gerenciamento e Assinaturas", - "guid": "e6e20617-3686-4af4-9791-f8935ada4332", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Média", + "guid": "ce4fab2f-433a-4d59-a5a9-3d1032e03ebc", + "link": "https://learn.microsoft.com/rest/api/reserved-vm-instances/quotaapi?branch=capacity", + "severity": "Baixo", "subcategory": "Assinaturas", - "text": "Certifique-se de que os serviços e recursos necessários estejam disponíveis nas regiões de implantação escolhidas, por exemplo. ANF, Zona etc.", - "training": "https://learn.microsoft.com/learn/paths/enterprise-scale-architecture/" + "text": "A API de Cota é uma API REST que você pode usar para exibir e gerenciar cotas para serviços do Azure. Considere usá-lo, se necessário." }, { "category": "Grupo de Gerenciamento e Assinaturas", - "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Média", + "guid": "cbfad17b-f240-42bf-a1d8-f4f4cee661c8", + "link": "https://learn.microsoft.com/azure/quotas/quickstart-increase-quota-portal", + "severity": "Alto", "subcategory": "Assinaturas", - "text": "Aproveite a marca de recurso do Azure para categorização de custos e agrupamento de recursos (: BillTo, Departamento (ou Unidade de Negócios), Ambiente (Produção, Estágio, Desenvolvimento), Camada (Camada da Web, Camada de Aplicativo), Proprietário do Aplicativo, Nome do Projeto)" + "text": "Se estiver implantando em uma zona de disponibilidade, verifique se a implantação da zona da VM estará disponível depois que a cota for aprovada. Envie uma solicitação de suporte com a assinatura, a série VM, o número de CPUs e a zona de disponibilidade necessárias." }, { "category": "Grupo de Gerenciamento e Assinaturas", - "guid": "7d474317-6c8b-4cbf-95bb-e609d8a03e97", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", - "severity": "Média", + "guid": "e6e20617-3686-4af4-9791-f8935ada4332", + "link": "https://azure.microsoft.com/explore/global-infrastructure/products-by-region/", + "severity": "Alto", "subcategory": "Assinaturas", - "text": " " + "text": "Certifique-se de que os serviços e recursos necessários estejam disponíveis nas regiões de implantação escolhidas, por exemplo. ANF, Zona etc.", + "training": "https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/azure-best-practices/multiple-regions?source=recommendations" }, { "category": "Grupo de Gerenciamento e Assinaturas", - "guid": "778424d6-1678-45d6-ba96-c96ad88518f4", - "link": "https://learn.microsoft.com/azure/governance/management-groups/overview", + "guid": "4e138115-2318-41aa-9174-26943ff8ae7d", + "link": "https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/sap/eslz-resource-organization", "severity": "Média", "subcategory": "Assinaturas", - "text": " " + "text": "Aproveite a marca de recurso do Azure para categorização de custos e agrupamento de recursos (: BillTo, Departamento (ou Unidade de Negócios), Ambiente (Produção, Estágio, Desenvolvimento), Camada (Camada da Web, Camada de Aplicativo), Proprietário do Aplicativo, Nome do Projeto)", + "training": "https://learn.microsoft.com/training/paths/implement-resource-mgmt-security/" }, { "category": "Gestão e Monitoramento", diff --git a/spreadsheet/macrofree/sap_checklist.en.xlsx b/spreadsheet/macrofree/sap_checklist.en.xlsx index 24ec7bff2607b83e0ee3cef69c19dde042649a65..7392406372e582a437868b67ba603a4854135e0d 100644 GIT binary patch delta 21307 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 F{tE#ImJ0v? delta 20849 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 M-6ra00(k4c0V(`HU;qFB delta 25008 zcmY(q1yqz>)HbY-3MwfQN`oLscZYO$cZ0NabE`;qi*)DEA+1u2u@kYY0by)uy-)AH z!k^wpKm70By=UkzYga3Ech~nG>{hPsHf+AmPN9h!NXRh|c-URF{HAflA|xaY^%UJb0yp#g_&c5V_&)mFqn;k$Ny0;2cu9f>T+UGAEJ zyJf=1+`ARGj)IQY`CE|eCZT8XrTez&jJ|;#-SK#8hspalC-G3v?l(7oPPPu#-=KPC z%x;hIq4X_-uyjnXkI3=Lj?L~Ho2FJZ?}5?aIYGKzs&2ozD>1m)IoJ_Aer=T;D5iU} zEEv25;Nk+AGs;2jZJoQWLZ!ZLnNG=@Zw!jf&aZ+2pgpFgqJ4dL2pB_%x;BWzEe!Y0 zyWy{0b=zJdDC}RgG1nn;)gm*UW=f%m848r}uJLW=_Si0S}grIt`VoR8#))9oAr zxagL~!*wJLBW^4BKwCY zy9oWl}tK70|ES2 z;3)U=9MbvY-I6WifZwZilGsN6@Z^@&4vz98@PXG+W}AztQwyJT%e6(8)ZpZbioxrLyk6VI+Z?moQ6t78%*efFE+qGgiqTH^jU!4}Kh zED&Z^;l22VfNw*eR7rnzToB$O*uzoVz!*)ZEN1D-pZyco)MrY4W5qWU!iaJ!z6$tw zW_Iw~r5xO+uG)pA-Cb9xqXf^T_`&13{ViYQ@QgxGp{(9;N9cJIvG;4&Dc z{VKnoUqrs8{=n>YyGeaIOtxQ|yVtoh8t|V>E>i7xX-D}k$?{0e3r+t05#42tK0tRt z>kW#CC$^M~EXBvRg>#i<1;p3hK6blum^3y%$bh&=j>%}U>3)HA(T)k6H*}wy#w4h` zdWfT9deh1Ge!P%FUi@NB?}GB?z!m`PjW4d$9>4_ye{5_*9Yv|qM5!dlR}T;H{c!=j zyzD2}L20N?ey2}(54Rpl{+D>q0Vw1i3Yq)uYy_yUHoln9K!(#?^kDL89CT=%*ulmiv5G&Sz$T z%h)eUEnaT5?fd)ftAJECd9}F6AF2UF&3x?$({HC+2&LO#bw1rm)o<=!0h5KMRq$_o z@xZ<7aVz(P{vFqnN}%=V^RVrLjcD5*pFzb7R^y8w@AKP9atA%8&S6W6-`IFeT3P{o z_84pu)s-3cic6#baDfBu;!=BQXExFIaXy=`ePEQywEUqnWP#r2YSR|#rzr?OKB5uq z9UcWxa^nZLd76F8Z#1X?q5gp>n#ADALmaa+vm;awUVGn>MAU;Y$L)aBuTb`BGvPy* zWuuuNo4Q_3?@>KRDdgHMU^?yFLng8P_-yMrzoowH^tAe=iyt5T<-IPdvSjq`ak7L;#-v_Gp(H zD238w-mDYiKA=oZhyNsRD@B#8)bmEUlqYbZQq}(3*)nJAaF%+I4?OTTSh>+`Svnix z4JZnyldHkGQ8#$m@kf>o%ULN4jR6&8N-0V%{LvvuSSeda44zMcu+TF~AzcRl9wzV%N8UTF!L}sd` z6CP6%J>z;Vb{W*FA|yxAn5srUaQg9^0Rtv)s`jndylb-6K_GIWl&Yc~5Is=6+6x)L zM4SLqsueEh&f6hf`O79%B1rv!2+HWvcV~}abLA3(-f3`0T;#Z`^4v}-;^@*1WsMBH zuGJAM@3Kx`{(f{c?O*8Osrte1K>@dMM02IQZzyIf~gC8yk)R4kV&Y(K(9Ny7=%D^BJRokX0}# zw$*;Q6@)Z?E|M1>i#!8U;*q$ioldj)GbQ3H&?UB&o*DW%9I7F-ds;dV%EO|etO#xm zy|5(yjP)YimNsY>IKwB6ZVtr{`_WL!OOnEXto=x6bFX= zHt1czqR0j}5mAyh)##@E9dm+5S2%QyQZ`*xPPIi*KKx89Z06fJ%= znQ_^eWQUzQX+fS!QVa_KD-4yrz*^3ooRzhi)>nA#khqsdb-3PB!=7^lFU=?5R0{1I zRrD(<4pSM8ivttxl&qwFjXs-{i5z+Q>Ey&_i4149j>u;{RB`wDfFU*p^X{VQS$gx7 zS6X!SPC<~T2JM~dc#$+2wU(hu+salUral@yeTUNz&YDhrjR28X>mdK%e72BEX%wL_ zjQKH&Is$Ki4ybiM&P^ML7x*~-RfJxc*Ok%kdFh4N?D`DKB6sV=z{>;}^!GUTEgM&u zCYM#=_C7+%dfBs!_c&t{hpn!eORyV`{P-lqJs8QUA9!=!`izN>0rbbHe_*4cam?1o zu5b2m(84tv7l4O5r&_EB*X%jtN;HtzSs_O0v_Q#vb;0`!X`K;Q zX$^*Wpd)GnP+DYzK4Md@E%xZsKmJXz4f~>h&eQt7WRWF`%YsVIuJQ?}q?W{SHf>hc;eS$kYFjcth=>=gu|KGz&eL zJF8)2)_A446$?Fg(zzDrq3NBluhr!gxs`XjGAvFNaBn#r&N0k7~5Ue?OD zZMshBirV0^79$VWf7G8-HoG6L=E7IPTmzOnaY$~ndi`42h=tDcC}Btd$7icCe!vza zTDbwDOdn5YJT$3LnjVo9oj5#4N))+@_`o+39wnlfvfpI!4WfF)f@WF*wZ}oH&uY5L zPEMdbR6-4NZJwoe*nXD#Hw|BtJ?5mo6nPGMB=?n ztrzbrZ5f$GD&-s?hmX)P+^Y3v(e$G~ z0c|9mX1rjbE~njT zX+Jso^iz6ZlUzaK0@hJkGN~Z%W1aG1KY<-8a0qg)<@O5$PB$g5L|)Kr@| z&ob>Pb9-zQ5qx&~kae;=0+&)@<$}qc4b@}b=V{L`0Jr!nCSEIz`Zr(k0~KaSs=BdHH*U|%?SJhD9LDw!4`@}9 z;8!plO}Sj^0+mSm%@Fr%)tuP8iHXyY-#ebo)A+*Nu%!M&jKRj}V{y8MYKeRL^3g1; zbhUdwEG=05=i-{`vmJRwU)WQ8e37kwKjQC(DYFgB@3jLJ*b}GDHF69+eGL~eYd--E z7M7id^eA63_IDI`D@8AVuAAt7`ehnB`{~OLP{zWu%yk7_Sd`owDN-8hLUYU(b(1jC zhOuClKUvo(^1Xij!x*$a~`gav$a^ z<0#zOWR%^CV#zGGe6fq?ed?fJB3^5oT!M=Y917KU((?hDt7ukB0H$Ld?*cZMjhcKSblsBeW50_*oph~*XPm3s$oY?FX*u)yCrd*pE zSU)jhHvtyKDbpgo0H0gndQ1uYLnT^+fShv1rNlm0nq20RHS3~=fzEIvja zIJ`8g2_OFPo?1wxV)-Ar6kVx{AUkz|CeMpzPz0{4X5A)kcdXVkpFq7#{_ zOV;Q1$w9$dXQn8Z27isEFMhVEYs>4jgV8^kFsE;Ub~89YpkwHx%j)T}c5&8DqO$?Y z@hf32IGt%D;&jRTKH_G+k^-2+-e7g|Y3>+!A@*_%4ZjQ?MorS!K)w1_4zXlxu z(|G%y6C~m`a|k5_^o||xRX18cHy)anNcfp*L(k*-XT#|Ap>txW^_a7do-5#X*+(e<5W?f zi_o0*S-xkT#JnEzwvY0Ky^{LA>vq3&WMA@m?4eu^eqUCrq6 z7j;j$VP&78YoGEhZP8Vzh#UbC$Ck@>_l?!kt~aoA%__)3fEey*i`@#w_wMRcOFLpS zIWMUE46D3Ue8Tlj$INR=umn_I6CkiRQ{&bEECQuw!IiiB@9bUdKx}Vxr{%G1a)i!d zl;oL#8Oo&{6ec|Sufw${soWDsU+mK`NbyGmRkF;VtdE&1ex8Wwh3xR`wnMBZrm;1PLWI0NtAx%W=cJt_tY z9o}c^!;D_mIdJahALF65SN+C*#*9DCxl*`3z|hyxXv|-H40RLqa&jdNGhTP9xv3kB)md~4io&p^cvDgCl;;%vOXsPhFF8M56c-caV24* z)oa;LX$=R@Sx#^el)HWHDaV!8H8LtWFx3Ue@!1UvJG9aFzHVn6M8?ySGav~24G-~V zO}je@MPF`yxPwZru5=%>a&<8(J73W@%c4rePo%bOy-8G+|0!uS#1Em4`_CVDWdtz` zngh_h&yL%JAfrT)1>ZX3%`Y99-O1$T@fG4zB>ArpX0>gAW1Ic1MOo-C>tMw572vEID zsW@~Ad3oyH{j0fyan`d4Qbl!8=`StX6tq-Px~r15KI5g*cT#&cW)}E(_ONlQJ&e;F zDr)p40_`zwsVxd-Y2YCh%~!r&9YWg4*1WI@H4)aq#X#^&FCkz?O$-HaP9|&6M4*$) zw#3bM&lp1b77hCx2kPZ|syA6Mr5yK9`&E7Rj4MYBPOY^c(>_VOGY;;|q2{-E8jqV@ zWKOMn`ZStHPW5yBOFT40d#2g9>o->xL(T_AEi;|PKq5lrPR2A?*uvv0xz#dS9_3DY zN~q$&Bf`qrv<2b+763twYr8g9@3DqH0IjXv#T5stg4643ep;ik(~Ee6c3`GaNI^OPt+u9%isEy(Ql}muw5gkZ zf3z>lzFtw}cX&%lq_85!J}trwYXm5hJd+~>xBQd!6oiF{W^Rp3j>JI!!DgzVD;@2q zYD0GLO;snVl@D<|3Vl<fX-n72wEI+Ghux(+ z@n^760N_)Jr#CYD_4NYJ=WXh6l&cy{G1U6}4aDh{LZO+}qlDv*Jz}Ql-=tdEo>m~s z;_8+D^NX@a?wgX3stpEjsW>l2ejb#7z-%@vfA5$w(oD%kf4qN+#j+gGpOs=e3uHqK zG?~p;vddgC3hx!})l##!EFX|rhd&sAdDS3>01Uf8=Y`$kU}%};dY;`th%ZNnXDKq$P|*rIEl0f|h795E`n5fcD+tfmoH!NTv#?`+RL7lslUqobBC@BW z_7mq2SvH9FXk~rKxZ%w+hj9eM2d|qq>4G4nak^t(J}=_K9R+dTs!%5319#O5 zh9>X^;uc@UbXQkejmtPojRTx65)Vs?$+bjP3U-OTk)KPe3>2P?Z;KW45QM(d6qh(Z zXA--mw97O|jUSlt82#-$FylC0JaA2h=$LtQs*|-z>l41A%Fe4O2DAL=ebwkheJ%i{ zxJuY@=Jph?=lT?EZoTQ(X)p&IYYfC%6}t)riukZ9&k3a&eb9rXu%py{Elb78Jt>6) zc(DYY?vkGd@bPkBbrQ*eL?+*yQ7*vWOdjWzyb2c(){%~vI@4tH+BS?sms)j2Cm2+y zj=Npcu4rG(V#?+C=P`j#8&<#jHZu{R(+0D=ASWV%_yu)PLw-G9dmnJ))>1zNZC>H# ziT-l6dRVO0!x^?2Og4@4EPK8XBRF9Gn+AKeBy|3G+WZw3&+}sSKt~ z7uUdw{1+Io8rjoaVT78glV{OXY3bf?Y*sgjDGWPv#liVjg0U7jX>-O62^^yBTXtMl z4W9CvJl)Cr7K{n_@zJ%hM$xH=TDOQA(M6)o2KxlPtxG^@3(-PfyN$b7jV-Isg639x z&y9wli<^7SPAEyB7qUguB}IuWnrInDS_Vfl)`>*b%hEM;Nz9hTKX_?&-j-(iqijp& zOny9?ocZNx%@hhn@ry%!_MhoJfPt)IgF>A4E!6=2M%OdX>l`4EngHfRH0WHp3 z|0E2R7}_!>o@G(F#0H&Ev^4=d?Fk2Smf+D-Q;{Hqgn?A|(^gHq!P6s`Wzh=1gQJS2 zSHLPEblHA%705jsrgGf=AmUn>&|fG;&t_7N*NvLfFn#1VXkvXI_6dgq$!IH$*6ZGw zK1+M0ns1GJGW^YJjzsagW9GcI>90C}YsSc-hx|*y?!iv!+N4FxxHtA#%XvVhd;YRR-R*wtN{_Z{^7U)fEd{4^e#Zn) z0eQh#8i^&^Z$+y;6$1)9e(33~EBZ4nN+AvPA>Cr@i6Kv)k|d5GF;*>sI!TCPyhv@b z#JKxuBBsCnmT$u8=}%?Ovb^`t{)HK3jRb6GIEHP}AyN539_pN4>Z9VGb)pJbqVWqk zn+BY;5JuL3O#&*-)mm*VL;BdPlCH_pwymN?g>8=ZJ<&1u%)Mxwxu_GIdJ0tpAC3L0 z%{kZNFC*YgW9wZT;1Ne@H%xwKLi#Yta;ZewF5p;&m{Ih1@anAVtRaT+X>mizvvW)` za9nM2*g)UMr*$j13Y~_hwMLQj&LJQEfOjk$pf5y~alTJ(Hj#9xA$J;l{g}qY z1>lPNoI#-=rQ9n+Ci?IYXXNE}p=$0neJbs+ZcR535g!}*tNl{V6-+^?Lnp-Ahi_T< zeaiFdh2&ntqn!DS$e<&Ie!K7lr7mPW`c)R;;0WI@g=7nGJEgarE+9Z@=-tuGYPaDD zLI^;T!3XDkRsFJpZ~mh5e{4_B(1at@A1xJurtUE(kGhh1(v+-BsFpFrzdo>3n;iI> zN3yuIkCzEu@2^a%yF$^MSD$o@?@-W3#PjeK~t1G^Zq`zh7Bd;}mu9lm^4A z`cXbvU9t*MSHhtJiQg$(Ao#%2SXU_)K+=fv4ho1*0Z2GOcBik0uk z2+hnkv|l6il}fpI)=T9iZRl4wTD0ngb(7oR76#*(Fe1OT8&eyV=x>)`6o^ga%D`wy z0n2WhU~qAEXB=-cb!hZ72j8t^dMaquHP{sSClDLY`BuX>uqpiZf;zoieZa2qA##5K z5E8rN&v+oc>vQ*bu$Z2IOWfM~M<`dvR1v3hHRKZ(F*kOQMk@Uq#|9&+(|q~(3|dA} zZC;#N_u{9iz+GY~c7B{42MP_|b*ahv*z{sv$x(X&rXM3(b}jYK7K(yWfM$iubNadg zx{r=81590IgV%3{>&oP0`~d@v;6QWl-yc^t#e%r(+VMn-pHUmF7?X>6-qy1ET$S^C z%!}{gmH#dkDDW|uE?nDAru@uN;DftR1Fk#^Z}-(>j=H<%pEOk(~YmL+JOFV)~y@db+Y%@l?f94&}473r`tT1*#zdBsh z>G-ls`9ImtfSGP^>@T?8;|gGBsX&Chc3$nrvbfV4((<6-qB@=n)ZsHMH76q28Q{Bf z-8gx;+ZDur3&7glkLiQg$#@49nU|Ti$hq!Iv>qSR#JbrprntOKR4fs0X}?&#a04_! zw>K{3x6HRsJMV4g{Tx3kqBSB;_ErcCjI&!nMyKm|amwZ^gWoa5XxI(Y)p0++vdpk9 zPC7~u^R5;<5H~7C&1BDhG}!E+C(?i;I2evNPLzb)fjaP{Z1Jn43}w1xgB60Fcwl!Fv`UMH#BfPXh(>x9{Ydq~q2-h2#BY-U|| zH!##79YoB)JlNh)dLEtZ{*2PLPo=uh=RsA$N~Y2rNvIm$XnEfY5GvKuruVxfXChKN z0A|L0b@rz9_brLV`pQCv%~-&Av>}g$*SKe1W`lX=zo$P&ZE8?{ObvK3 zVvwN+{7qjlGj*TJL+CiJlgzD>fW0PczA#%)jM5TO8BV^+QMzuOp4hMRJ2MZmf&S9X z0ZZ-yMZf096zEG=Bz1+;vw2-qz0a^p-IoTj2Vk02nBNuCs^=wt_HkZU@z)4vD--@M z=x**ljS1UThiw&7CEQxa!2T;Vh1^x0*`C}thTqPS{;zOA8*B|Z2tcsG^rSnQT&3nB zkQX^I+GJ*M)-h<^pk`Ss@q-R67JOygV~TQCBP{&A74=7%H~!AC%)*+{KQJC8|Fstm zKWrxyIRrVLyzZu+|FY=t(n)#rGadu4iauPW;L!6h1*>$@DmVM5sllT~KdQ>A(qM3Z z)x4_!kXn@cCEFFSI|{#OZ^;&k)4^LDslH55^I@tlmpcA7K~LA&Aw}(iJmmT5 zCp>cY%JzmZf-N7v%+m!6WD!bY{M}3Pk3K_%6UEy7;LF{Ujn!_oqqU1yAnf)caguGN z2h-}b893OaLmFMEMjJ=xux#v_89GODqq)@m(&92M;4KdQKVPYBUz|_=g(t;~Ku6iX zJx!x;Lb9qyXUQ2CW(H;^KI&fEu3>&ErTNNl!=Klv0#AYUG^^5$JPYK8PLnWzqJGYr$qqgR zpd2tmIQve@{W#Q^*T;vWIG|OFhK?4Io!Yl*N=j7{HVqDw=vV&}xSoSP$394|JyN<} zp(A#JotG@X&GpG2AA4O^jhGgm@@mWyyb%=>b5*EG4%yy!bU{G&P3lvFu=^7FucWAi zjj+-F0Go|iitBVbdqb+lH*{s`8DUf2?gh zlOBb%H*aDmb!}>&eZp-8-mU|1(Y1_MPq7TDC+Tt!ChPg&F7L z5cYon%$G4U4{i!EI{VsUK(UTrEB}M;uGAL z-ymh?Z;!z`Utg9PpI(%l9SA0ac5q~=>Md=ZA<-nRCBtcWH6lwV>`X(9fof{8)z_$! zCAWs_MJJ(x=!WrvmXgkCXEIFnxDRFayf+sd|K)(}`_O!oI2yA18HrNl`4bH~nXA_< zR=Nna*6Mb80aeFQt6*@O&M+lpZrzIuoQ%Z@&-eeIm;&CUS%Z7?7Ew_SYStK^7@?az z@Kn^ZfucJa;^O*>P-S!PS8N*mH)9+uyVzeia9waSt$4=)h6X_`X^wi*f4(d#1t1YWXgf;o+=a+f>dP!K0_Z@ zw7qXdittY0QsUWkBAptegyG|&R3~mVz_45M>eh+Yje0=Jw&<@p_X@w!bs7^ows8EE zUQ*T%G#gF|EZ(+U-;4>2Oc+dXs0U)jp1;5JY>G(luDC~VsGAlXRMdu~6Z@u79EC3N z1om*a`x|1qvaYYlyAI+Tx$&C<`n$abI2e_V0SjhP7WZ^2{^^!QUaF$kAIu7E73U_L z2Vu6RCWX9j5yf>rJG6F{?C5CyM<0B6okODtfG&7~x#z_C%V#qf|hfj^VLkfE+q%u4bv@X-p3PlXHqV~)q# ziOPr~W%7LI*O=1z)Y#F+<`R8K(=z*%huJ~%l}ra{rrZH&`7Mw|e^9>B!oPdQn zWLD?Rdnfyud}0bXD6Ti+)6@UiQUqAhLVzP;YAlX1%)8LJV|PhDv!T62X+{n8#k%5m zY}%vJ!^hx9MNRb=D${mBE1b%6Z@I-cHM||BFEfy%szJ?Tc*5K- zjjK)^bqtJlLUHi?F@=KE7l4_NdI$gh6Iq+#%G5IzBEsG;@4K#RT8S(1Z)fJL2UqX$ zqN}RlKeM^Hqnz%F8a$1RaBDsu#*-)yT9!`!P#bo=I$lbgYSzv;WA;~b0WC^hV$wF~ zBGz3EtENSB3kPSYx*=$pt|p*w4ksO%dn(*`y2HXd*gYJz(^^@2;M}_Avx?a`PUF>pkZeF?t@3mM8mc@8(I~&(^QEL5Mt2s<(UM5w-GdN|N=5HJ%3^4nx029=L!jMaqaNF*+>o6q?@eKi1y53>y z%%Xt76rJyi&uaB&oHS8YXYFhH0<7~UeeULOX>wu20vuVa8$DynVI)|WUEbz-nKxfQ z-lq?}TNs;KT>l3c!nTuatc_7i$;xVCIIWa}ID=W5zg3|5=j_ej(Z3-lP0_alFfpcR zpvdebuIv{tvFF4NNl%i$Vg<&vKrCh4+w7H_Ifvgsjcq_`z9Rj|8JA{uCAPjpLQ&sj zdv~x-^n$&%;j45egxB|l{V7uGGeaq=^ZNZNexuI#88NLt+FkwPIZ2i3GDSrv`);oe zX&RQ(8RDWLcz7B-cBI5{e0I^m7W!^`b+e!~9FrNsT4<=zIIB>#ec}GF^|w+e2~n!6 zbFz7!D&C;ey9pRkX04%rMtm^|QeV|ap#HS}UMJJrL%ug*1ki6{xih+pm3Kc37OXqR;azfV2EE=HZ1I?^&LK}5q#>FHmJSgWTSlFSH~A+u z15Ssf*%#GXefNnJreooqqx@Gx@a-!1eExU`ra-(aXpT^3_VMWYjo<#qgIpxWCC)ZJ z(T5V6-?eVd|Dl@_UYb_jGv1~#3q-tEI7#mqBrl*vANF_Z4~g4H4BOV;Eu6VK_4UX& z6_*-rk=aMp-6#48{ImCU`Kh$;-%TWBQ;=crcaf4|&*_%D#N=(*@x4N=7Qc{Sex^wR z8vOH>H0)Z&PDSx{4P+@pb1gzP$Ur%soFrfpqR+w`7@Yqm{E;>y;~=N!=RyTKueA29 zt2p$iFKcyt`Fc$l0o1@L*)ETxKViTz6YttYqOWm)&&5jV{^`SsMCajB%%c8W(ED20 zq-9k9lV_2FPD7+ZDh~GYEZ&{Z14N{K(6qsT)FucDIWiR=fDcIk*&%Xh}6Sy;4 zZAPAIG*lUC(k}4VcpMQuc9FqNrQgQ_z*)6QQ%(?rcs*8Qx zz?lLtsiI!?- zh$}IsBSE)Uke?Lbn@9e`|BKHt$A!!==q=gCUA{Jc7hErAhG-qah&#>XT;&U;u z5fx0UT-xkz#9yP!-b|p07D57e`oP&;4@&UXQ(5a38Eg5po#$gCwajy3^o2S0mM-@ zw1EYInG~LLjp13r^Z?K!n1a!vcjcgLdR{tJaZ@aR`f2xO;M=VK^33m)2H%Oe#+sFN zqj_)Tn_b@^M;+M1@nqSmuQue9%3nI0YPlWg=gEWUf0UFj>sky<%O?UIBd!lR&!lqa zd;;sFf>~1))+Nt&hlKweFS{V#?H(tx?g=JiRP(emKG3upp5N}CYsm~^lJ|egN)aR~ zi72x-=HQAQ(~U=~Kw7Qh%X{mI zNaEqQEZHtQ87ffH%FjTL;y7sZJSJ6gyph z_zAlFVyEfqeR*v&mvOsp(yF;9v-HdRtBVs4%97iGlRPhL+7pi)cPuUW4ve_5s=tfC zx4c(jeO5B@Ip?1eUpLMT~iRJJ)wF`)3v3?wS+1myv>suHiI?J4#=- zV-U0z zHT^Mps<}$FgHaznqE4*TFaI#C%qT_*A{7;twc7VPh9~6P1bc(s6ulMFPWjbzel5;k zwUl~&L-L5{ekH+bKc&RKTI7?p4?PsLkZ&;qXfhU;=F}DlD6nTzON6a4g^f(md0)&< z)h@b$>lyrc;)pCpkY&C^W8({8u)cl0X)`9^6|>3xjKeA>p%>`)f7`bxs#3+=tnq&? z6Wi}(jx7f#x{#p);C896C}l9Y_to_IUi+u5!sVmy`CN{brkZukLP+dZ`QnDOPqaX) zx_IS#QqUW8Z`IXuLxTE8D+I^Y7>%hjT&>y(?^um2`#t;mRj8>lP#j+}J?M=bl&V+h zZuI5r*4n|guvXco{N%K6`F<{$Tc{zqlplA^Kz7dkTbww7wgkmEB(u?4tO zwJb1m9QND-x+dVkQn7)Zgsz~uTg}^F>BNL;eR~s`YabvzTgm>7-nN;`HU7_wEr);8 zW#aG1Cy2Q6emR_+UJ9@E7yGbNS4PUSOeao1u8Z^c2NENMgqM&Z~DWe+7mMQtwZAm{bc_s!kAMVUiOk&314%U&XX`c#Mg7`oJIBY+l z$>>(tB;@uD7Kve5mE_3HD06!=MMFaZDdIXgM~IO9pz`p~l<XZs~7bV~63}@}UthI6EJ+kC*uk!TK>=cBVv!*v{Z2nLC zP>^BywJgTy+`{C5XB=X8asX)bu^OFf7`WZH2OE`mf`f^bsV{yPFP^X4ujU5;HIU zO`qJT85=tSuRh7@^?d(lSJm2zJ?&8G=DmNk{(@e% zp+WUcY*=zIe#gOm;AkPv~mq)r36PF>#JDq@ru6lh`fH5rq{F zfX68}9il&OG9ETGUfCZ`wf8Aj^T~qn{%yCi35<*x{hD=RJUV~CTy5LY-1c(s%HTr0 z`{FS8b=`Q+O&LM{=*@(LhDY1&)G?uW0Bk(;Q?n_Z;Oo9034P3o%VMJ6W!S$1B_2BP z7Oj&753jfD4PI~2JY85);0uGikY%!e8beXEyJjXQX4)In8AP95q(zCRN(+jqqSHW> zF}fY5cp&s2T;^59O*rU~>`dsNq2~IzGGrc~3o{5+W+@MM;TJ?9nQSmxyYaIiYe-pXtNvyeA=`MhkjZ0{=W@ zb`}j3t|Ph@K3S+zNzZ8ba+x6-GEw7N>s0&w2BnT#f9D)U>)b9P z*@mmR%^#Dm9ZF%e?rUzeoVZL8bA>|uB(7wzA~+uTYh{6HidOtv?3Fmv6YB=WZ4ouT z=Bp?MvTB4+Ho|H-ww@nd9nikX_D?p&NQv55*^o=Lab-j#pX9}hUZso$Af#K}sj^)g zHb1;k3Ld_>Tt3e(C@F^uZeXSFex$`>P%}K6nEV<(BZV@&%wx4I*SZa#q?DG#Rlt6@^9Jd!X4@5V%kHgJDy6lW_FLBG{o@@)xx~Uq#$M zf<@a?;qR_fwdJ#l&BfhDn%s?cf1qQH1rb=ZaGW$KlCqcfd+DO(?DR;GTmuZ@e z{t(e?CmMn~nEDZ(Y2k(B_A%~scN!X3q$6Kg2cm>jy6CC>97t<`gIHOmm^|?c(1V`* z>v`%i8cggrQ;4&6IVZy7H{ONyeT#>Q(IPD_|FCe4th^GVlF3oRXatN(+Lo0qFVMM9 zOTv__+7BBasb`7h9(yi!(Glp>?5K~npkWE8SXxHyk5Q>nElB_eV%-4^DYn=Wkvw zC)s6E=_h1o=o$epjTQiH63_va&-hcMu}v-v6_@Smx*hs^uHBEM>{j=H?ArZgIdg1W zyw#sxiRV0okmctE7&(GS}0*9M>%l7g71IV_>{Q8kOr<`Hu?Bkk2a1p0ibq zVJ5<-B7!LH$W%zj8=KFUv`tQyl;zQgrUKW(d%t)H_8@jxAO3RsUtU8Xnax|Pl>6vd zB^HM(Z_U_MDc83Oyeu;pbyZoNdQhBRNhJ-HeTo0i+_<(R-H+`~!v3{%z}$uEyV9m0 z*yQiF%Tyuvda`SJ_&J>%9HrAGu$8Ab%ChbhKc*IMgjyd;uiBKu6xq`YH@?nvF)F6q zB|}jvwtD)f*dt}(p<((t%7p;opr^-PwVhJpUtpR=4NF9i6s!p8?r?o7THA9|>VBg8 z#K}xFs%9qH04wn+Mc7U?qrBw5o8dX#Pen(11aujYpgt3vIsf{RrixB+;-Arql$B;U z<;G{NX*y1xsk60Hd;GcYNGc%VJ+g`6r$v^modbMLuf@dyb2_Nu$(P=7gzZA12ER=k zaJJLnrS;bgE>9a!#=^@vD@qea`Y{mNG?3cUc8lQydS>PWFS#^b6_`&Ca;A1?vMlEx zoRfE@ss2Nkitslc?R%3YjtJGOc;Nv!kBH9QsHQHM5@gKd@_LpH zj0qY^gl1<5m`O<3cne{AY2(7n5=O{F;wmN#^^v00HkJDJeI~q!(Pkymomj2jP3OA- ze*?tq>eM*&YC=pN?KJ|~tBZO%orq}1IQMFYK|!OY&wnRvn*OPwUaO5Zjf8|OL=UHW zjEBu(a|I4vt&|3;-NKCk#&B?lG2I*zRJOy&sQ*8-rs#g6AE3h>Dz2;f_BlUvE_k*Y zW~sMCO}%w2IYasu5gZYfAnM_|3Q>@mGMiz{i%wz5$xe{s1~Q0=&q0y0=_z z@AY2NX<;HLeQN#!A~muNxwH=NxcB>!jAtU)VNf~SUCq68$7;k|MM)ENS&QCk>; z(?8Pr(O^3{EUC?($eBjF<<@AA5-#NbqkE1yp8uB1tM)^@^_KeN^@AkA z|6M=zH$_Ef*Z&spG4gC77|G{E| z^Z4bXnAeX8R3dD?)Jve3j(C%Z-drEY|DjdzHJVm@EUp+4S+T+olSOX}p472u@iC&G zanmO$M-;!5r74t`_ImCO(XneY&X(BV`afJLyq4x+B_mXhc&AJI<8#E;9a7*9s$MqC z-3ue}|B7lcQi&tNmOg2(m;QzH-E=s@P0T+$TOWq}viV<#Cb3E!GH7|a4Sz-Rxj}$k zfaViTCnVLp&G^&*vu-5%rE>be8I^zipBbMw-^~d8|E5&=MgN5@-TeQn?aHH?xb|>Z zOkJXYxCG>h5-Sx2L9LP^phpC^VxQ8-Q*lK=kRl`q6of0aPl5)bAjN8^78j~0SiypT zf*L_wLcv-DHv~%nSwxM@>`f6MoMzh!c8Vt5Zic>o?Dp!EEv znKO(U-^&?zd^^V}`^P|Kr!F=ml$|xBs^Q{L3v#ujF5U;L<>IVUmWQl{8*|nWnS9%J z+rrUiKPeLz_~ywnA0vbdv_CW*C^=gk={1fF4Dv3xV}Vd!aSI;6Q~){K|2BUH8RgG! zjZIF6LiMtnc0dE0G7>h^4s5f8z`>+18hft5Q)&GzYYV7q*f)%nOD=jB(q9uleJW0W zSb(QpGbD#1Pdus!5UYnv1}eQpzlBUw^fqJ^?ojt5mEP=oyz0oLhSgiqak-7vLvjO1Z)cg& zSzE{~IfR_itvu(Fl$P%ii?_avuv7b-QmqUxtLr{3e_|{QyxiSOumEdM7giTWx*U6H zL{eKNdK0PEGRqBD?ZY$c9n&kMLkZOa)Wab)Za6j7EEP2qDY{UT2yrApn5Y6l zI`rrVN#QcFnO#SI_fIBVT%zuIv6oL9SXH{fMaIxpR04E1Gtpw#(;%HspI~HKpzCCC+;`Gq`b)#5R%gNdI>%`a3QdYc z2z-GE1gf1c*SNp_qDBe=wS0=np8ca1*?cw$Uo+26@cu2U$+kXSPt~WsTVjj)tG+jJ zNdWW2dY{drlp&NUZDS5cDm~S}@P7bpi~P#0UAFbFbx2lb(W{5L9;$-v(GOq!TnkOF z@wV%$a$jpv&h#3}44F);6ylY_Y#Xk_ve8#nihukR@8DmY>jTZzS6q}C`Sp@*0H&~N zJd7pdE#6a0x20AI>`%EVYx4f+rKNR6(W0*%(uuOQtNo*mC4OY2?5DXdNp|*Z^AJuV zv2|?bhn08plDU+O#U*aSSQfFJLrmyS^$auExB^kyE|%7DMbb`^f5jh;D|o~SIY(;p}CubI3*Ji5_JA=W1pHxuH8XGJu(yoLR5zAOK2n zBZ7rkXle;yaZyy_he2@96C+}plwR&X3CRA7B@69bN&VWkU5ZXQ3!$RTs1 z3w6LSQ!0&W1TCK8l7B5b>}*S7xII`C`TQGHR7d&M0gZees4CI65fO`!OT@PlewYce zseuSIt88|NU1UsUpWp zZ>6(qX$eC}^qlWt-2vY^D9Tt9dwdPITkBH?Z^f90V`t-cO{o4#7)7wgZ1t3#0Qq8? z=*6)VwyE=zeo@ZA#AkQF)0 zrzF^)uEC>WIc4$f8>{$gW&4ZlQf&^-sXx3N;EwqDt4%^y95zuml`5Y1buSBe;bvdd z06ok*+of-K;q2+I>ee)jl?WHm%_1WLV%MVAFIqV*`$_fgDqQ_ccPUGJW+t{%mGZi* zSmJJLm0|!2SG=R}P-2X-)iOI{d_?T{#cDtB{L;YGN@WDI;ZZ0& zV?oHD|Ni)_dSRl4T6QOmB%!$rs(9Sb_F>YstG{uZ#}&r|N~~P5jYO!_E^9+MyHLob z8WHB)VOtWNsg&o*!48mtWlLH);&?*ccJ(RP0cxa}RbqkxK}2>E_np1OMV+oTteRIq zK-hk*8QW4L6c7b7RH7E~v7|Lb9IpY% zL@Ffc00mcJ4#HI&Pv8nO)^;-NrJsZI0S{`j?Ik(qwE*LXfc~K<4~$K8Dl#2PT=zx z6M>U*ig8U(}W z3FLctk5Yv98wbPHf6!#yk79BK_~(e$uo(%twTCQ7U0|75+X{9HpQRW#bG3laWlLO0 z1Z$fRQ&0t-93m1*Ak?BjHr3^cNXfXTLIg4M*G&Ly?)2~stk{y>lmfP`hj#>{U6uO@ zDshb~5M<*}`()$mmTOTGcNC?Qpim{dSBX^X7UK6KGQS`mbrEg}B^|Mj7OZB$6g{H@ z8l7YWoH+0p_Q`;jn*qH5Y6TDO21QTmSLlF7)u7;UIk&K!&b<&WqSWto9t(a5#S9^4 z3BY7Ty#$r`no0g5$U3(Bqej7gL6JO4bc2|un`Wsr_6wxC^vrlUbEjttnQ0=go2&hwwdshqjG7aPh?ek*H&46A2 z+>ri~8)TL=v`}1Bf{|6#&~ku7>p7)@iDdwgw}EEuW;!r2sX4VD^kA&I$){kJ&)1T%C7ltNLo8v z_EOTiK(Q{!)gr;SAjP-f;oap`+fIA>pN_j%G-b_f&oaSM&g=TsebvPxL56JQ(Y9&q z&{5@UKeg|XpU&KwUyvpXx&$B7R~XTIUmk3J%>C$-^^*4;t$P|eWPvGfdL(6ERk0l% zr#QzX_q_{VlIR9@-kX;ecf%LJM+e9Bxtc^tANBZ38|FnatIwV<`>L;chvLnX_rSP4ASi$aDO)%duU*1z6S`@#c<~ zu37P##<=Y+FRPHRRJ?p_*Oai$kiOA>jIcv??zMlraL>Gs`QRvsh;F|Up56I0Et}KP zP}#LmzQDH2-F&KUv8?jV6G55eX|$r|wReC*P!!d1b7jo;fqC=FYP0{nSSnk@;jN4s z%S!^zrH}lKrB+w^rtVr2_Kex#^`73FvZKkfcyo-j{oKr^;@3mMq$6S?9|u(*ZJWC$ zP3m~X^Qzw$g$HHe%$sTKz~7I~Ee5|k!f9-&C;t~7gx{N*x}P<&~mDIyF7Pu zhkU8?$@c1Zy!Jobqkms1$>{8Iz7$=>xY{`1n-}|TyQt>a+6wE^jZs0*e@y^smlxa0 zolN<^>EG#g3fLYIb4#wXw?lTu`0j*He-@q{));ua?8i32re7VSfbPSy-7lBNZ1qdH z;qrM-P)~J(*h9t&aC~MOoYfh3H;*n1+LhA%`?FfPertBOUX!A^@z}^>!3KN9vQy_e z8Wx@R>#0muT;cZREBXWxy@$8Tyt16z-c0Y9_jQ0*_v*fNKl~BYWz~IU-A~7R?_cP6 zcj>mP#4nBK-I?=Mo+S(^`R8*X7PoARaezdzHI43G% ze)Jcv@NWZO3*^r)ID06VJMwxfI`TT(tLOCjbmcxVTUkMGkxR=$=Oij#IzLnRbwo)O zdrw6dbdPlEYP)Hk2xNEm^!#Gb`8?=EP{7f14;p1b;p6BT@@V)ZzLSbo6;E%< zLu;RnS4i#RJLJ$2b`N=fdb@(9nhvx2a5!_Yd5+8Uq zguRJMY8041$cTBCDfsG2Ttd(JF0)4_iB)+zwX2SG#cjNQq;#XgfczYM7f*kdv0;oJ zjdpxEjmD(q?Aw;Er|ZDTu?aL90{=~37$QM0tvD4r=w&ar1-+Dneu2GYhs__R`W}Mh zn6SC#=+(9HhF6p5G+OB-8qFAfD}nN7w@!2N{V)sc8uerMb)j4J&+gcB$z#GTkuS$^ zGhK#X^1AS;laST_9BA@r(x=frv8B;Qst?e1>y!i}{}?_29k~jR+~1M>INW4CIx^nl zBhE?q^$3=B5-E-4$k&1J9cbGUzGr#lchUGPx%cCE}oeiI5xTPPy+mJ k1yjo51WxjZP_yKq2nO=GE5c0oYi{z9h>z*zq3F8*12Ol41^@s6 diff --git a/spreadsheet/macrofree/sap_checklist.ja.xlsx b/spreadsheet/macrofree/sap_checklist.ja.xlsx index 27ae93f5d02923016749df0296fd2f1b2f72b870..aa9a45ed8d7792aa6abb232154b9b576338faf7e 100644 GIT binary patch delta 25860 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

0}D@mLB!`kjj?r{M>^3v3EtTg<2){t zaE_`zBqM9j{Jf5OvcA@?jx)aW*ht$8w$ZkcwsE#4qR!i>?p+t4%8F7?mDf2_st!(e zE_RnK)PA$Q@Zh|px|}h;*#n)F5QkS!G<0mGIDA83ns{L+}p7fd^ z_qJelvdC{}`dYdm9Y?>Q@P@2fC9h(UERt!DPP5|Mr-=O(yC1*T$}>@Ape@ph52J+5 zz#hl;V%Om=E0Mi0kpGTqvZ}wl$Z_MOZ6(=d+47fNjOn90C$!y+lZ;9T<%Ci~Wp)Qe zQ_hM`S+!S*d~t0!0rT8Wz)aC>-Nm(-^%?u}^W-qk$pT1k9ZVVC{=o;l%{;K^ZNVGZ zTcty)yVR;xtJOB@$nS>u8a8!ZNaS};GnEC7yuDz1(biPHoNP95W$5G!vTEm#gn1b! z1&NBMgBZ4O+bWT7i&J+|H?G;Bq`9l;l&^^rnIB8tOI4=^PzB;FFwZrqPh>$%6j2ID zTlr#cw`Ib)wR+){=#uE1=xWF3N4zGIdAw`|t<+`%q+*dIlJ=JonO|;kHtd5cDjFpy zYkp{N?_4WL3=AhQu8b^fPtI`iPPq_H_>r&K+n`qw@ZgZ(eh`?>3Z8|)+&5q)vz%mi zA#y<3r>bpTVx%cfGq$yWtaV;-*B_CshOf*q*6!!TB>U}=V+P5z4I*_b(!Rh~#teUP zyJD5&uf8G;!Gg7p>w=W)qLc(i(!&ZV6{V7*mg8T625~3y`&U5dv^Df-Vl;o9x{~(G zB%{QIOle{$>MLK8KIlxK>bdD~mj`ON+?J?_Kp7FmMW$?vlqrB}kicuJh#;3M7BIQi zYk*6c2}2}EQ_ebO1OQd$B^pP-bUoxFGJ%r6mSKuZ5kuy3vFrAIIQji0yJ<6f%^~X; z9i7dL=*Zy8O0JhEZoL$$ZUCV zLoYXk9Q92U$xYBdeg@p|(z_wMu=H|h_6E;Or}$_&cJe4an#_Jhp8so0YO~w+DfcNp znSKQX6KP+1xVP8Z-~L->OI46S?LVTZm*$A% z5F0lXPw~Z3@-M*m5jKcn3>#=*1JC{M8W1rIk*PX#8a13IgtFeolJ%y(-ZUW6mCmy` zgBsy{uArDuR96yLF-v5HYRx9HPA(T~_o=s%t;Xt*ibanLrWk}VGa#5dx`WcdyErEd zOMz%PNMOLwi4}riE^Y@U5Y65RgOamGv)pkJ%q1F8Fevse^zS0(Gc0_urJI_B{T~Xm zdz0P|>Wk2T9D^j#C0*Fx0`3Aa_DiP6KEnPjLJQR=TCKKgT%>Z4-B83g5#D};Asu0V zKOuHQ+`|57goylzh5u~EZiInU{y&^C6VKT5RP%rGn`rCu%Xbs!UKsCJRnd;FT3oRlYeT%o zPsGC2hpfgd1bpB~6lsr^?xwXLmWR6eaEsMA*(g!X4=qg(o8mEB1U;tMm3^wzSH>}J z{Xm#cuVTqmF>d{L5nZtIAdq>+p`$|e|IZK{z<==8&`cv7CJW*2&I-RwGtsjX+D%w2 zYagydZ_{3B78o8E8@{+&sPZF2Cus*A6;Qsk^NtGK=Ot;k92KDEOKMK&IOd_0vB*@p z#lb?P7OO2RL<0A4TO<{w;D_KKO!NuJJv@$aSi>^xy9r{$U74pU##w<{ydsS;j+rn% zbA6#wZz}5?1#p7fPBHg>c!s2)eG*Dqsi(5WO&@!yYRTfT~Hc~ zEw=o1Za ztKAr}?BRA30rx#@A*;LMpVFl(cWgqe`)ttuBR1j?Wnnc2w@8lZ#MvS7hTA7`w~gUB zhQN9IP4`@OrN52`q)^0RlT_3BQ-EF7^CrDe)fwBvL+ z41p*E8HN~k=t&I~YRX7&MWid$vSMAW7u}`paKdPG>-0SY))t}+h~Ewdmaq+^NJn|9 zh}3tpO6@4E#2KRrT&#k)j&o($Uf4t?o@|fSJ<6`~(Vx=CEvgT1MZSyviZAsSXR8my zm}LichC>E08JJHX&i-H$guRT63L+}N5(^typ@I5X3G5E3?#HPGC7yU|^>SM2MZ(WpoTU z!iE<%N7x{L$gr2O#L4d{i(eY)I4`5_aMV!PDhIu=ERtT>D(jUOa~8AW+2NgD3NLJU z5nf(;l14H68dy?M0d<1^k={jkVHpl*Ji<8OT}DQNQEj1xO%-e%sHI`^u!p^jCC+mD zl4~gqurLB%hGEt$LQHxY$_RR4!yNRkWT)37Yze#!+bnp`>O||Bu&XQs?@LHzslS}` za>&5+Msk$fm&?e=afA)mNLJVjQJ1MfZ1gT;iIZMI7QNsRA~>yqV?wP2NA-mbbMOlb zBly)QV<7{9r;AL0Jt*t|M=k{zw!H|jIRN-MONODc9KY26gytMi7p?2cF0&lK*ro1r^2?zD^IO5<7g{(by9kem-^emO!h- z8XbC#4)}3;QSICAtjxx&vBJ4-nNL~Y$6MS& z)9c@_$`pFV7R>eceV>l1X}cchKzk{Il55Gf$y!Pvd8{&i9|3ZI!vFGgZ1D zvZcqEcXeq)PbRmvUwU6CKfLEmv%%A0&xE{rv4Xxs?ZhB4Oe?C;vuA!bv0w&rY~r=1 zY%75>94S!hSn?iHx69dYUrT07Ml&XS_H-6h-VYeIotz25ij3ZMjk*}-VW`(aT3awW z)Ed#NaO%5d8!347#rz^1dYi9dq1~{ewyEUI^%WD)6ApV4IfYc zBS;^)b+xZ{AAl))wUSckfM>J^duuK5m>KdRUbO48V@gk{XwR>)d?(lGaV6un^3|W}1roM&Rchu2cKXQ8_eJ(*e7#5s>EC}(_|R-{ zpx&vI^s%O0?GJYT+#B+4jm4YG*;hN)4VzYTcNw|G=@gy5_ID56Tk}Jgh{GlH?Yh0H z0?!Xw)$^Cpc{?Thq2fKilugJMSG7ItW&hCZjk0ajVk-?Tgq-d zy1dZ3QH9lHyAP0H_$uopBVkO>dX2~Q2cbtgv!yyz+XW;l@}=MXJV6ETRFfUE;||%J z>LnP;#rCZfB|chcZcCfo$pFz6;7VI{wjXYeo_&Rao8`fu;AYNw8%C3dq{qMbB_K2l zk~Z8YjD$mdq}?FN%W{0X1s4{4KM3njSoj@2TD{LY+9*ks(ec)nmyb|rF0LbjTpS(o zexT!enqjCQEWbMx$9?z|?dMQQxJ3!YN%@@P;yM;^+&gfK3jDW?C5n4359@nMXeFTk z!C+c@s1)3P4zvg%G#o@=7|rOEJS2nS;&K9pF)Y`>H4L?uL@PPJj&=?bS?LxE|KxuF D9jLOx delta 25801 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 diff --git a/spreadsheet/macrofree/sap_checklist.ko.xlsx b/spreadsheet/macrofree/sap_checklist.ko.xlsx index d3df24c32e9b29ec16bdb10e599d26ed826f96cb..837c0b0e857c48df80b55a50a403a8a84d419612 100644 GIT binary patch delta 26529 zcmYg%byQT}_qM2jf`Cd1Qj*dtB`pHd9Yc3_H(ZrckdSVqVTQ&T8UzG{p<$>Ikd7f| zs3CuR^!u*${(J9Pcb)z0y`R1JbI$F=;)Gt{JWyAMaty}kQDXD*bQ29tnT?XVg z$ZdNc=jP$NP&$_J8ey}myrQU)x5}lO=$d%x9jaxm+Ux%IE!0sx)^q)Fw3zD6dAq1KLlG0a`p zG&jZ z?%pHdGqKvw7u-4KbjM*tPYfUwG$#YwG3Uezzb0v+6LOl!W$a<xeiyP<@Zv#&3x=_z~cHeNlAAg(SAg^nck$A8pzmXqLOdGAp(R zf_rOp&S91<+b%DP^_(Rx&$6#*um8-UFC&AGI(8%h|NaF^lJ2XM5;Xp*q-!SAH6|5{ zuF=~|$viSM!?O0SPjQ z1&ntMv3WJ`L`QFf1v^y=IbC{oR{HAzznbiuW-j`O{e^5J*@rb~!vt7(uTS;vc7rdD z9qU^1uPdM0hWOfvom-#pwS0AjarwC01p?=MtvfSLzbSr^L$Vz95EvqVSia_*rhf2C$c(2TJKUiNxabS zUbApmu-CmkIS~C>F{fn2I8E0keV2D(yLaY7(@!jSmydXIZ7=3+vYx*3DS{Y29}7C9Btx zbUX^rb<48(j*F&N>wUa|suX(ODW~^-)2>P_TqI4`>!|kJ`fi3(^?@rRZr^iLmy=a0 zs-|oKIlpn?&Zah2ypMPd!4Cz0phE9`sK58~ZUc9fsnq{ze{xUxq5Pv?_eM5p>mTu+%OTeDlC37iXJDZ94?JeVJgIxEf?R8l@&D)B7= z&XBP0?qxnddF76Hy$LV)=hxKe@ve`IoXRB5Qn#nt7s7uI_W(!34-V@hEp#3D54r;T zNJ5E(S=Fr8E!)TsnzfIcSC>h#UCQXL74H+dY}+|UJjwN5QVdy@#0O$kHw+2fGje`d z==%A(Tbss}{Y+)ol`}SH@lx!0$A~-UA7qN@rG7{_4t$)u?ku7bMJyV&s;8@>JY{7H zRbIfRj}hwE0qEY6+^O+7(xN8`3vD6y=w>VGoEFLrN=UMwosWOt*$U`KVGMHVd8YYk zql49bzOcMOMOLmNQtbn~%sub!ts~KQZ0$CeLc!8s7KcM6cOfRu@r(9m+j?kO?V2>m7~M zJtx>U_lF))_QOjGNd&~oa6HL=CDz>=-Yr2Qb-ubzNlNh8A_raSrmtTk#pc(X+I$Rq z`MzU437!%UC(fR5@AD8*EwF&WWGhm;-1|Fvn9V*c+cwY#`Bn}eEzHY zGX7edY)$HLrCM)kv7e!5cS;x~Az#o^U! zMdb}E7ZriOVIyx7-X>@iLZD3vlUoa=ll`;anvN`zA%59Jbi1AXdE+R2py|;|xJ#D6 zv(T8>Bu~L?Q|-$z5T^O;X-rQB4C|?+I-NA)P==otH5&OOpai#+hVde|F{sW}WN3tx zv{Q-}?y~tX6&nfyBcVJ7Hn#8l52sUoU`|jftNH~|>SDJ{1%U_Gr%HBD90JGU9Uaq% z1(YMHBYvfkPS^yxaCsnsbbDAL9}$LY5JM5ZMqOz?*gv1OhF4}TGVwx2Q~p(ym%xDf z*o)<-h!^_Jst#!@y$DjC9N$Tv`gHQm7+Xa(wqE!V#x#^Gmpl%e+pYWT0+Fdx>-O|~ zgnQ9Uf|j`o`RLWd?Z<;$-o2ZpD^hu43wgzfk7>a=wK?PdHr#yx`aNAPvFBd)@MCi3 zCSfZ9^=eNlpWyXrgr6CG22;;N*0!9}9V(1jGUuZ@k6o_QHha3Ed1bdq-SyhIiit1Q zZOi`Ir=3(wu5S)NeiB7Xu0}c+8pyXrL=G{%vf{!?I zxH3Ii-=Ys9Ff${-v9~kK&1o=$GDi?Gn71};Q|E8*-{oGsQfl@?1LrGQ!WYIljSg*U z@&Q*b?RY3^rIZ2deqtrrG z2Ge(H>Nf_o$g7?5qkRm@ZRzPSJGpWgcx_yLW-`oZI0d7r`Q5oDaJJlc0`jZbMN4GX z;;plk)xiD34BN)V*=Qs9Q4m-^x^t=+CO#E0Igq8_wmV!bQpU|XLGjP2&~D8!3e-~s z1@NC&qgQ(SP|KULM_#YHy2J`T-)b_!ti0y^YzCWif|s(13`*+_(N_#zD2>XxsP!t3 zSF#%FI%n8$Aa&oBXbjlsK4;9->BV^Nn=y({RazEGBVBCP``zCV_UCk}uqBHp`R!X< zkwC@mKWQIJ1fNZiwyx$_cMqeD-3?g)o$B;4k4qCcv^{#~9nuvpr%ihMv>~06lY7B& ziJ=g!ua4y^4f^y&SZYd8V70u{qDX)I_rwLZb5yK3ZP+$kGCT9Iy#Hf=q&$Jb zyRVh#8O45EprD`4aY|t|(Nw#Dy!_cvbb|6J%XHId&<~PL(YEp9PoEp|<_Cs>{#cq@ zR1y$z=eX9dJb4j=oVK#}3yh_nI;3^(Fd<$Xeha1|lD^>sw2Jba({nRHvKKeO^9JYX z(3+N~gQL$&0e(o@W`-%*s`3z*E7kBmVL@8rZ5wGEY36X|0(sC68WtSSHVvFaD5~(i zLdeB#{dZc88oscdkXuD}8NFeH~Lw4`<4syU+CUXO|NsIbq&yVZYj zi>^iKk?eL*O^)`=RrRLIHSS|%j_9n)7E#>iG9xvlgtLD+qXnWygcPxSZxPG($e8i0 zHC-a5)lkmF+j3f&6N%HZKX@rk+YPBgx`}Vmj&z~Qoeve&koC-4^IbquY8}N(3yu1| zYATLX<>mmu1ZS!g>8MjPryHUro@v`UJ+MV&>};_8`b_2)BT=?2eUg|F*zVhzL z5o9M%X*I2OM1%_gdETgS{F$c_3N?WDewPww$}7FiX#MtScJG?>p-Iw#{>v*ml(!pY z8)-+_zH#6?uEHo1cMhONb_Ev!#)6>rT{^`^Ed#>2~22M>_GT)m&+;Od1(C zWmHNhHxoJc2{=D|Hiv&jkA0Vc>Y(5e^~W0mJcZ@=B~Jo+O9efe^h&9-d;*>?p?XV9 z@IYpPpW)OW|HV?o^JM3Z1-rS3@5XEbGU(;V)f|N0kY32u`uxCh7{1X040d{3AYH7b z649ISCyEFW09}@ZUbv{PV>T|DN9H9))y~mB6RPoCEhYr87fPwH2A%&gD6Gw zN)lZ)z(4h!WLEp5x9(Rj_$h49T$;Z?CXqG{qx6Np8uB`T^6t02;4Kiz(4S{t7#}6q z!!2ZF9Mf0@d%vmP`5a5&b_2s^wIF^%4G&N@w3v>jR>Dkh1&Sbwdq$?#QY5+7i+KW} zQn4J>V)zOF7*MuMM(+BZqgUaL)4;!YqtwJ3zvy+DXEUr!^L|QsEHbN5w+(OG_sLAR z#9D)lYl>WiiKjKkR7pyBLqu_-!?axl%8reo%J*R6qZ(g_XqlO4C->gGngm$L#l!-Q zEH~3Ll95G#lc;~0`0Df~H$h6af&&TH;)lOMBNzCfh=Wer1U7QFdTUnLqc2H`!)1l2 zI?_elaiz=4m>kn9KJ4-6@f48yMLI@>RwY~CL`9yf{eB8!7;1h74QcZ6WXnAInHP{# z7CH33=ovvUSMbIcNJ<3o1IC8OG20MoW%a{@SiUEsFe|jZV?<9`k#jw@a&0|2TohI_u6qI3iWcvby3|W){Ndkh6jrFXw~@GWzf}a@tK*OG*4&Rxr;cBXmgG zy_dSb?ex@iexjcpKN?dRMX6EhS)r- zgeg(^Xh6-(kRGei(Ip4Dxq1k{-@p|1oWtFGKcv||WcKpKw76Qg2+OKueYXo{AjA;E zAs!37W9{`muVuQAHsQ%$O)R)TY9(NCnQ?Rto=}1ef;e<<_;g4jN$VBNZfS=HSlWbP zVZVGCMF7?AAH2fXZTgC<$LtHhG_8jYzl+??!R7KZt#B|7)j`g)6(Ze$n|7xqZT&2$ z=>-%!U@P33QnI>RKJhwO0v<_dYa=Si?pi(e4;y2DE%4zB=JXZb6e0hJCZqYn-iJ~I zy}p@A0x$2BvXMmGbaiLE5&|cCtv@ZjodAwVaR}@2^VzX1>x~rrQIR~s)^sr{eA7*Y zagHQS>*o1YM0;~Nc=zXOQo9qYk~CzeQ(G%8hsf29#~7E;5Ww-_))efGp&t6^aVXy@y^C)&LI{p*RVoRYe!5{Aw>>!BB$fITz| zA&GS5sMdE>LoT^Da{7dVRu@6T2n{{_AX7SsHu{7ocYc3yk+eD22S2WRzbm+yUyiJein&ayfzBy-h=C7_6yR~--^0(Zr-|o$afO8EyR5+DpsnIL8 z$9Pb1kqiH|?DD{Y*ZE>zb_H{-wcm$=0J?k}C3&)P4$vedCH^MIdT?2oP382>%|GK1 zDlt$!P3U|)MYpD<3uwLKpYeFmCO#De$@()SwqPd9BJHcH=4NhwpP8MRO16okSX<9R z-s8fw+yXs|(-@@?>z)(!axRVR9H7MZZV}Bt>oQokwr|_akqmZjO|vZVYyRz&YAk&2 z`;zu&`$G1wH&~C`ccX>L9xzgVgHU+hY$n3uWiQq3?{G}EE-+N%J77LF*?pzuZEAOJ z3k#!ft({~Ud~JDqJ(;w@LX@)v`}XA2s1l$uC^=Z+C!S1w^GcBUh@~7>SWRS@xmMgQ z7IZxM?FGNI5JrDdwWLW(ZP_gNe|x`Os%>f^PjJ_S>pi;jPU9`b*aOMieq8UXAIo$w zc;K`+umJa*0xiCwqnmjeGgyUf9mYP+-7Tc+@OUJD)1o>aMwdAcVj9;1Vk`B-CB}oM z2B6`>*~F1+7Hh-56c={gMFZ}_Wf}UOk0F?fJRV6W7++b4C)ifNkK{eRRCXo}AG&8e zCdr!nBy*Qy&XMAA&Cc4<=gse}FuubI?Q}w!H8dcg@IX)C+sL&Cw$TA`>t-`X>H_;L z>!y_a%h$*Y!pT?vnG1bD*yU?fqG#8oIm7R0GYAcG*jQyAfJII^y~aGqoeWUOh?pc}R)M7F#r~^i8njj~aJ28ZW$$XFbH@|HEAXD(^0e~7bao6=Cmfu-)0?ceD0OGg6GWm z&yuJKls=tp(IOQ$CdTvT4BSKw)*DWZo5p}VjD>b^r?$jg424v#2h7PPYo3cuqRkJ% z-ds0D76+wg7Tq=yzm_OXEs(a;f2We5qTiGuw1Vl5?&N=vCJU5<-wk^LO5?_GGlYN2 z8ZSjo3gzzaY(pmj_uAT?_sIhBh4EHoo3VC^$pR6~>{s1P8DcXg68U`uR#&z%=edt| zfOp?Hzt~kryj!eEiL(P$wWfXE@g&PUrExWGA9% z%sy9W80jEyu!_REq)3tjvn8unp~sZXHBkMUIbKRGsbZS>U*-fUTmNmcNMvXrbEue5 z38HIRpH)k%#Y^vCv)DXnu}v(j+@VP;|93)+WG~XBmDZFzSTa{MNqt6N%-kz)D!C`A zJ)@l+pV%oqXenE(u3o2D1qZp+WwhWYPCY!%H;`K=RnpoARwJ++w6<*A6X5ZfiX!v2 zVbT1_N|X~(qnq*-<0y|_R)HJoFWDV%x9|@uz9sRFT_w+xNorj|-rUbbx zqmy3iJ-XXB9j|@2#(^Plm+Sj)UmF8|&y}K|{;=Y}XpcWuj?lmr6H>hLdmsO`p(kcV zQ4Cs|Km}U!b0RHBcFC&OY&Z}dfIeF}#L739mP~{p#0aLI1uG6hbTK!ivDW>xH7i6> zas_pv%^zUZImRI0Q(VaZ+?U(eW>$JI(~u7~4p+tu2IZx<3Fi)ZOl9k@jNAUV>@P^U z5=CPS7{wx~+GP&$-~`K-=D<&ft$$f6=BUT z3EXXNHh59A&X2ofJw9q?9w*Pe)XUMY^O+cp(sm+C%6@&!EJ#GzB%-xNt;T}eNbW5e z!M-EoX*4Qrp0p9J4%_eOv-8oTR* zjNRfELIM1Z*YG&5yLyevPO2Sk@A{u`;e5QADx1R6MF$B3n?}~Kol{&>qXK}9=xnEu znCZ!dc}}7dwO1VS>r1`ccmJEczOX0XN(XV^B+!BsdYF4lbyu_waL-WN**p2)o|s6A zX;m$HdrqS(4b?CfB$X59fRdlS>95w!V;4D~?M?Or2S1fdNGF#qL`&+ zr#b`jy=WvFX7Mb0bH{SXN2@d|qhEnIiR(XTgY*om*|)Y$`c=-DRI6TCm)r0!*7# zaoVY0T3+{+k`qZpIZdtdBtT|A+mq#jh+HysoWkEh!i$I@2?8iEe=`BvejP6THnqDI zf2XPw`^Q}tu=iK`j-NZ(?{IWQfaug`v*``Z>=L1hG`7Zan6-lVeva9_@UWfOv&tZX zp-xC5OHeJ?v%GWBJ$-{cp{;O{S!c;g-OJmd)La^x>bJ1pd=QUWZUDSMvnbA`8Iu#2 zIygd0ipzKQbHw+=_SrnAmG!_@otiAFvA(eaEJc8#kFY7HtBE0}YkZy!w+)v(F#h*;Dar~yBM<%ah=w`=ocUq zr~f4hlrX5Y_hiMAK*;H(xfBtzrIx08VzV@`_BzF8%Oy`gz}!B>+#q9l=rV72C8zEi zaA~cle&=uP*tG;}t6Q3seS7C)RMe|&pq@xXmjjtStru>N^C2K+&!B=8`!k|@>YW`@ zMjX*^RaM@ep$4K>Nr~Df=uHVs{jbivZM-i-#GdE6&RVePnodK4`MX{c!%yqkB#y=^ zsu?cr6oc|@yIt_atlZLkj=p$*&jjpkpF#Q7ER!Ue0=i$eO6Lsy$#MMs!)x2pbxoV( z{iU-ZoWIEe{&{gY6){#n6c{4c-a@Z7Z<=2uRsx<~$tMqdOzPjv@8*k5olm-+&?++c zI*G^{`gDoQF*X3vE$q0#1lQYEk?FWna4%o53TC7xG>j646Q4EwPOfu;0W5~%-&`jl z!zK8h+Tub>Q*sa1s;Og0y;h}z^H5s8dFk^(dC4wpgdxqu$T^?lbF7yO#i6K}UJTwp z(99~eV{G~%DXP4AQ*@|irOi2din8b#MlS@l7s-zG)-V0{Z$oEopV{INSUX)Ve^1V+ z3Wa1^{7&`y5HHcS4`A_s=4*7D!fBC?Zf+AoYMBTR7?)2F`*VHCa8@oEtqrNhEhFed zBAEC~ULF|;3sbHuxN@8Vc~N7wH|A0=D{&nJ_aI8Iy=c{^+_AoJ>CO+x+zH&NZp+uL z%9RHXQC8?0?nUot9f4hi;2<47^bvZGSP+gzQPheq$rbmCCDP{FvKs^ zg6NwMk0>qCGLs;U=;XAq}J+X@`FjB>>z6@ZM%4FJn~p`A=SwF zh4G%%z4M4{X0P4hmOn%me4`@s(rXFPMdx2z;F+&-Y$(Q+fj?-b0BsM5R zJ+4upl4R%1U|aP9c45yH9*fvy30Gj^daqfX;nk>v0pqIQRGm!|G5ZzHidvurFd0HQ z-4iswI5gMV%9p2LW5F(AfUk>|Z2nDhtXwr8t(+7U%TLb&s14f`>xu&^SGzRh*4xDE zE7IY*Rg6bZQuL($Ny5E~EV{)lHcJ2}s^)EIVL;H?lhAfLkmODdTK@p$tG0Tn?IcOD zKug=eDLMEqO=2Oc$5D_1lZjZ*eE$wR(wu!!RS>{h9dcxDuJi0^%re)jjiYzh{;a|N z;HI~boJXmQ4ql<0V{l=v!vJ@)=J1>fC9>eB zBT|Xk!!Mld8e<4=R;)Y%aT9%XR#WaC`v$SU#9f!n2&o^#AQj!tbD`ktChq>+UIuy3bXDr8>>6hT+b363Crw?!MKT@D7RDY8* zZbr!3%c1DgOfeH+&S}XJ6-iI*H+>N?O&yl%hvw#wvkv;j7pCSa`|kU7ymHX1H)3|# z^FG+}R(&tz^T<*MLoz`qB~myQBf4ho5U_-ymxwlfq6GTODD2@_C_|DvK0Luy)} zZrH$QTDRS;jv<`m!JQbuQeX<5I;q+I1)tTpCfL1J+eiE?qqb~}A>FAz4(I!hw~z05 zuv`!B1|Hi__T93H^yrKr3P;jsX6T})^G}IbybA z6xDSgFDryfL91j@NQs<36Am)0NPOkg@s=+JQ%bPDPRW1K8D-v#8VU*G*AC&2^mVAritr`xv&uR4QjQhb^}9cL+a3$y1tv#Vz; zDat^bS@Z5zdqDafjfjl1|=y5o1cK#a2Q zUUTd(_@4Zx5wgiagYG|Ljgr{bX5llrMQyGpMMJ~WcxK_c&vxwV=Ekx2=MsGjX(`sF zUaj3#JooxK?ClHYe&ATD-{Y0HdiHyqVzM)XJbZbB@0Da;;P2S)T}xvBonjOjm%ScN zptK0Kwg=s?#_a0TKq>o=h!;R)G}$?iuhyyFedE^aDi%fdPa1gzd`2Y*qbtb9A*v5~ zEEp3hsPi-puKX+E=6OkrJdhEKLZd*0~!jZT0B0{t|h13BpZg|o_>mS}7@!xpR z57Dg2W8uAj){h3?c&&wFLRjD#=uz3>_L_H!_0fv9Gv9P3>*_f|EmR1O*s32S8Pp(p zmg;0I)dEh^vIY7;?Wb3f1(fzx+VkpAiu`>)i*5A{wTgTdgNPEOYB1f`R>$gUPx7-> zl$6ge5?k9~8rr4vRN7Ep!sis>R{p(`4{CSTt|{s+3(3BA^^h{Mh7I(*YZuY@Dfrp9 zV8!n?=a%*^zdktI8xbXP)0i|h|1gCw%C_kmS!IoeeSvJP%&rt5)4LjK53e;a6_({P|_S}0Ei z&Ig4d6oQT)FGpgh#@xdq7wGd9hcXbRaGZ*Iim!9K=aJXc^_EYv$)imy(ndadM-i|l zMlb20$jp(Xgvq$`Qm<;wIvAKOl{8^%S2o0{e`OI0Z&J5i>kT_31r z)xFR}KbhmRmCnqYOLj0F;s(;@^w}Amu`pyb_bxxQB1x18)w|OY5I338EGVg?KlfJn z=Y38XnG0Q`k1^DO5GG#3Q#B3#z1JHs(PXV8f}sH&`#PKacOo_u7L^4ww63%uYzMtm z3PX>UNN3l|NuEPaUq!b)cHtS2V=P&}wpNRU(=fcO#>=__=m)u&h$b*SDE|}sZ!iwi0RO2oQSb2WxW{x8 zrc7TB(@HpmPd(RZ=M`vQ(Prd+PFPXZ4G*%scT5QpPP7zlWe<{UTiJ)o`UjP@_mqyw z@_!B@_Vt!|@>!_fS!mczv`PqWDLUuT8CyR_A2F*~l*011pO>pytHE#u4Fn=;MgOCP zmhIifATyLVOHS^ZQ^7A?qTVv<$9{eNRqV1yE7v;Oe^Z}-ok#ZiVACHc<;B4S z=vm_TO(#rDH*&>=TD!mIitaM-Ygqgs|IvgFsH|rwKq_Vq7tDEM z6_``lM!3d$FAc!I9y+NbK?F9U^_OtcSp$gFz*iKzzuEnonM~ssN9G%=i%ueqxv!|Vyr>s&7 z-c@9(Y&Pg@S*>TB+U5E7)^^Pfr}W(ko^LF`<$9^z00&kJx^i-sskYtwvc*1k zYrW#ymF}5Ev_%$;s5<_y-q>a8osi65dABFY-@bw|dx!hf#njl;Y!kuV`tv%CxcIA} zF)xL+e>A=QXKMt3VOix!h?ManJdz;1E?ZptS8ShG&_L=#JMP9~hpdJ51xU0Z6z17x zxC`KU>lNN_@Jh9Y5+QfE#3ssb1-4A|xU)P9VfumOFRfaYs2ciN|4n)pkizKT!^t`i;ud+yamu=h8z!kGx`NCMwv?Tj5r z3T-Eh?RfPZslZta%ACoKWIqCSF`K(nz;$y0=^l^$aQ7nF)0EdY_OY+02ZW z*^m!adx^IgJ%#yTiY8_wSYrPrCK#&ux#05S<6goEgAf=7VNjMc>QuDfc_d6S8oySw zyxG)wZ1~G0rP?4SXLcK^&?GS{vM*DtW|$IJz;TIsjlfMf{yeS1Vq)S5ko>rU`V=GO zaHYX@o0T=93Eb^OD+$2}#y!3>unTD|1uS!snBee(FFDZ(7;&CB{Z$%R!%_0~_(V z6+@4b*4_J})Hu-#3{=P-`GE=S7mY*VK(zHA6`hhz1D-vw=|`6Wt%WAu)t(qH>5aQrFcpl}MB! z4L*)4@8h4gK0-U&LK1l>n|7$~AG^thZRgLvCx+*Y_q2WxiWR0{{@@JHQq=6lZVo%a z+-V*%$N|K9aV7g-`s89Elgl?<)$yw6Z{zq{p<45~r_7dyx+j8D5aA+0AqxM^2vNR4 zUvy)S$F~;Q#adw&VS^t{LjNLOjU_3|ci^QLV!;Go^(j0CMMx4nu)|sQi$gIZHMX=jM$k5)_-#b%yn!i$Q|rC*WU{ zs_Y8kppC(-oroMXDm*cV4Dy;cYd>1Q>ROpN@}7HGMx zSap@@(Gi0Fph3dSF6uWs-c^A7+G5}%rm5~h#lhF+|E5=s~`(Ua}HA7r|Fh6mA^v}s(d_4f1R zp2C#Do?kRN4@XW8FjJ;))72NWR!0%vT#hl`(E;bzwL6e!civQglbM&8|6S&9oSSLE?4=d*q%sffmLeB1>YpBWF!k2Byu~w{_VL@NM7%8G}{-tlK9+N z)&I_9`0?D=xS+c%_(~z?+|ABDjujC-U8M%|t1-iT-$lkh+CX@|RyhaG@p}2%`ClG> z2ON%T=zn6{PLlw-Ab#zZYLO4C3snom25Me9LlcCzMsa$TTAF+M1&7gEz9(k)V>^vm zK^2gcKR066aW~6r4A!O>W?;>SpK@>h{G?A?!VdwaV$@-k@9_D!>T9tXQ<36i^Oi00 zhrv_%9$4XIPi5h#2R|%Eu`I2~sg_X{sF)S{R@U{5oOE*b%|B@%O%W;x>lA!zs`YX; zoNq8T!08U#3y{Y14SNH-(_Iasc57(mha#Oif)s_Cs)?>+V(4{H+XVV+6Q$p5&0>{+ z-?vt@uxkb)%^+NI=SaKJ(|erfRCx6Xox}E1k^$!n&0a5*Q*zfkDC3NDInbbD3dbg2 zGCnOVGb68}`bikI#_|$QZb$RhLg@B!<<%Q`w(Z^|QVM_X$ilry+ z9BzeyqlLbTQDutg>9<_cgpcG*1U;#cNgd92f5|fHQ4#2Vt3Xb!u0M8gP}fi*xjl>T zfL$k!tTmM~;c$v<(VDq+wOXMy6u}(-#aTf>AyE@V0Q~0XJ&LtP_;EoZD$aXTE-l#w z3g$Ct+S{AHpkff`95OI*`jfvDq=YD(FfOFi-mg&I0nY6;n>2`*(9_B3n6{YU5?#o8{5zv?F1!C49! z1st|x5RulNAknC)K4Pn>KeI+l`@W|}L$9_r(?`j;Ctkg?`}3z*UwP?Id_VlR41Tju z;y_7DmvMch2;(X47DX0hlKaM?LqNATA$=;aE3W-J1cK?HetrX1)O3k zp7t`u7UFe2CisV;fO=V2r^Ynbx}(FlLSZmH@gDz@2QDj87 z#G7W)AR^oD=)|?@*hHz2vGWyC__=iDClL4eduO$*XgGgm#ivrs%Cb+@W_NFn!bkd? zeafb$3DPqJ5K3&mi$na!A>rJfJuoX)@<$Y3{+CXl6mgki#ab^Q9QkjLd)!`|P3D}eUL!^j-VkzvM_L)}wHBYdZUsJ$#naYg9Pk$ZkQiZ_RIHT)HUbVg5 z-zJahnm-=-M-ju>$aY;D^G%^aw_)P$JiNJn0ZZqIdSJfAE}GFcguh~pGAqfCXXnv>&nwhR)_ef^lAha9z>A=CVIuU|5eF-j^wh}=%kA(j+U{ttYLHuyw|?3>M;q4rT}wU_1S;H z^x_G!MS5yFlN}bB2w5!x+d1utwY8J7|9$=69VlZ39k7J^iY$exj%LxIu(T#iZ)bu5 zsYgn2OBKFy1Dnrw{C3i)^V-*3;Odr}MalD^oJ^Y%f+ygOtebHPwEaMSeFbvJ2QPP^ zV5rkMdYVGU{(Hv*xNLJ!c;pngWMri2^*N*XSA*^prf)@ z`RUC8#k*HQ210>2cI6*cZ8L%x-#QD#csYFVK3x0l4OpZ`jU6Aazu6kP^YqS@26v50 zbx%d=z-pihJ-Er4?(SOIDQrH;A45cv$q&@L(hv%Is}oKe{Q1GR5u{n2m*Lgf_^$Pm zAPOhhH`#Oh)|=>hAfP2l9jIVdM+3UscsA3Ibcha5@uG*xWTYh8jG?Cw{>F)fXn?oD zl`LRbdD4AuGt71jPO5sX*}c5^=bUok`m^oG=c1_VI+Gu#Q(LH&eSD?yn~bO(`yOPn zBc5L~DEA$0KO(U3!aJryY?vZPh$h!apzlMG{r?7cK(WYvs9q<7)pbZILb6W^wTbad z9L9G=lLxNyvhHY4^wh?%K6j2DvnM;e~#TvPGTdpuDA6Q!R~^&Kg6 zMfz5CdT0t;I!3y{8|VHQ*8uaCIyc-A``Z=*7`v zutJ>h^$usve<`fU~6&s^7AC3>prVU)12}y&e6DevcIVP(YaWqLgHk22ut;E1=Ofbnty0|6JaA zQgM+mEm}4$Vo+joi8gyYJ)1tCMvQpgN$;Q=vm}r6vD=gYFNJVKC%XNnNUo#E0O-_L zq|?GWYIQ*t$czdA$c1Z?Wn1RNBzH`z*86IwYcud29u+hz%~ri;VYdBHE%G3thN+Br zxzC-NGa8}j+dqQtWao$7f4)!~J7K0r`|lVk7Ozxh2n`_$Lx zqCou83C$%EJyKSMy~@Y<7N=HhZn{%s^5cz7Ski301!j*rLUpU6mAtmTLPXGz%wpnQ zwnvqbU0o!r+fOubl+yP8kTgR?)@taSPz&i+$3FPDzIdC7YSsTuX3MAUCo@A6fAtp*d{@JlH| zY@@8EA{8~M$T)~|dHkNX9 zJ4JyR^+Bea$3I$i47%}>y~p9Xo4YmlTA69~#{?|x3;+~a{D)Ca4BTE{<_ zL?!_(?||*I9GBKC@p7!Nm=lS{+<W~ zJ%@azl=P`g7Cf=K5EjQHSkHzl@;PT8WBs?)GQQu=V*Ju=;=F-*m%D?gZ^Uy41boko zR2bu3FyxgnHWgGQmMbn5sFOQeX2CVfu5myUG9vylo>CQ=%R|9sF#*$?q=p_6+)xxR zPpgP4WOf%T(s>V3#6Z=Y;J|+Ks|PpmdJ65)GQp(_+0yqkhLqU#FxJz0Sl*}9Rr;rh za(+=nXjTT)^n)J1^A8=Od>5WjeHQbA@a$=1@3-{+gF$z2SWiKjf!{SiJO%tF4Ah6V z!F&w1ol3NZzt`@dE!%kUmRHY)hvMRN4@IxsOM(G4VU{e zJ2x`O-yEozNawJXP7cLY&U(0qXN9Y*Dq-8rMvdgGIg~Qi!r1Dznw0j!`09eQwT1P5 z-2GQ=``O7~G;Xl~w5AHHWXBj`!&TpP)D2p1bEiILEUO(&C? z4pPJp9`{U4ucc*lE83P6g+m>fgkW)*t=~-LyOucrwW9d6MN6EZ)}bX%A`vuRw&aF9 z5Igg0H>7TGfwCm$v>>|&@;F=dQ+_@D8m{nCRA6v(b;Q~Oq{aP42O^>yb~iDS_ACx- zP=9NNL&)~CMMv{T=dquap_qeHoE$9Wv;Ns;n+bQ6h_&bhl_2-C>i4++qW-=HhnYJ9 zb-yhk?AKGTwy=&qk!+}qgDrQy#GGl5;&Y5_q=@H%{&~R*%G9=sId{z zJ;^jVy&IolP3h?@!WrZ&B2+TI=p-RfB8dIeNkHp`=qQQcme|qv^(xFKFn_5&>Bx8o6T9d;@q;VSf&aeT zRm*HH`O}T8mZ!JZaEJxjs}|fgi$57pJc<*!ZUbXWR(^zTZW7Ef2CuFf3y9Og#1D8> z)voJK%Y&_on}Pw;@|#055qA7J40QEJ=;x*QFX9UMe!?Q4(7K*?>zc&Hu(eczyqBNN z2s#9Z3vNDkv*ho+xc(2C`3)sG+vmwEZ}Oxxh2!bFj&Bx`de@5l`k*6@LN_(6=$*Qr#S}fYdR;j^XRvT=7 zB;!tNB>I3zwj`e5DFg4+}D{JN2)-L z(mLVit>;$p<(@lMzWLGNmtSe*tDkJ~z+WuE48t7tfR|d|w*ZShP=ZuAo`SV{$d|RE zPa`kd9D=i%CUi+)Z$0HmXzONpqxQ5H+T{^&NkyCh?{Pz(4VZ(TC)6jIrwkz?!wm)W zMj9(VMdBf{tlbh6QZ2OnlMFXI4)^(X8O!xSDkPE4YAwIwm|xfZ`nKSI5j{ z>*2zDYlKr{{mpZe zE*K~_DTWq)WEbu!-F~p+QgI0javHPR@F0s`wT%|m2H08<`Vp|vbk$cvaSK}1N~z^E zDlGr==p#~8{+ehKxyHjry>@1HWy z6ab>D5=(_xSP%AmtLXCoocNBKJ-$5NJDh9BlL`Q?&sTW-E|JC}{-+`Pg26)f_Dp)K zGWLM$u0M0gKO+JpGt5!r4#d9%fA}@nS9~!RpTOsSc8n>P2Bo-)4xYb*3v`nPJ2)V~ z@AJl|hDUhQ41#*N!;etlvhKf$=5PQ+9}==Y34GD z0pwTXffQ&rs=wu6?|AJ9Dp}U$7+I6G>tn#`VGD+edh> z79nfAtF5OsPbQSqU17QHdjsjL-TznHl?Ot#zW<4AsX@9-nn)Bawvy$_lD$GHg_3Qm z8!bqoLB~W<28D{0ewL!tm5LTwvX*XCHz7+ROCs4r>HEIt%y5p;?f$m@@H*3bp6B^I zpU?B0=N!X~y)zois2+Q9ZM#c!+P7q{?RU21D)DsoAg!-=b3ebWxT~$NNl0vv{!w4G zDXhTh{E?jan7QQ%OFh1PIX(NcQyS??&gw4nv^jwlQk4!71)c3H518FJX8k-I{I2Mu z&^t*E$;XsU-Ue#Eg8eI8b$wXY?pCuqewWVLnjKb9Z+p0PzuVuke?%_j_e{oMY*}-K z>e9U(d3FZk;8|4avzD^fv}jgOq?OfehO3~*4Et|sTIT!3bIMnZ=DQDEt^Fh`Y+qXU z_U`#~r9ztZZFAo^ZP{mARcqt>s`BjG$i;sbK9ucN&h|ZGH?uY7vPZX5LbhwTCaM`4 z&`e-#tK?s*!8<$Gu6S;H?7@z|+9cLH{*BytU~4gSqNOupS4`g=>rL&BS2eNcP5LR( zE}#AP#3M&n0n`@3qAHy0fAF<2Ay*K)T#Rk_!$NZnrY z)}$?NZNhU?!}&Kl;+wz8on>l{RJcAbNZ$~BoV>f^veV+_hpeB!Mq9wj0SDPb%80|e zz~K>?v|ODH1(i0h;&#t1wtF_KzS1UMXFZ*!>6ZNBv7bM7oeL_rE~^^K%k=X<%lkCQ z;wbZT$(u?e33K}krRUXe94_Abr@2{q`HtZSz5#dE@mOUR1-p#>5hLz;5~);0z;vFc ze<9Cqy*_~6i2`%)G3*QJ9)b3le^I(g()Z$UBc+wWF zdpb6D?_6g(D4ugq!ac52(?^@j1BZETzx|%JI}@~rvEOdL{Y}y==0*ATb*p2P6E2BT zvRq!RT6Iop3w@=ab)R|t%g)%?imSz^ub7+>T5Pr_7`?O(J+@kh>=`=ScjD7ErQzjI z!#$cb`FHACtS?MIB~=}{M%T)tF{(#2rN;b($+mE@>o<-`edy!goK~6LUexDP`Pvmg z3J!HOSkYu66F>KUs+ycKSH6A!t*X`ghAB5MQWR7N6HU?@`c*wP_Qo8H(PJE{_Hig4I;nF*S3)( zMRX;cR>bfX34pIpvA25u`80aP5x?lyUw9FmVF5B~c!UHDf8@m*?mZUKke|zt4Ui3z zJtliXw&!JSwU()|j^74Bu(#W|TRIkd+P8Pb74@4s^z;3=fP=HG4OaBNpC<>f(Vuw= zJ!QS&H)=`F%3j3M>KmE}EDsS2Kfo9$TA)sndT@^Z8@UF6IPmNNoO<~GkTOI1P|@gVJ@azq3n|Fh~2oP!^VGBtZ)J;NjQl=iINl~^D0RB z`XaJvtZ+%@^h7g$+Gh4vWQooe&b?0-!o4SK;a-D9?7d6uHo>jDX38^EPAQ*KS*Nkk zoWF2!Q$VzUQ={R6vLNL{$1G1-8YjjJoGp;6tU4{=MB>4Rz(mdRZbHp2LCqpC+>4l9 zD}vpns9i@RX!q`f-DRlV0D|4WFuU7Oy9(ps)?sGt2xb+ra8a}U$1D+cyh>QSy!d!$ z%D^=6I-_<~#_du!qiNVlu)6{a*BFMY8i=OhPl3ak?ac6`mBKuf;}j!GF=Y|ea&gce zS+Z%2aAJmDkbv|B#4*}A`b_E{`W!pYcoj%fLQ1$S(RCAZ#q5F3WU*r}J@|POCy4E} zER?1k)hi2fPtaw^i#7?*G+bgl_auF>mEhxcjp^K$0hS?_L6%I*0udK|Dt2~;UbFzT zGAD^?h-iymKkj&ldW<2TFJB~IAYUT?K15ZTjGp|`2B3jPuq0LLEB{V@tcMfeTY*yB z1rmaWHE><0QfB)4PSm!GMx`ENAzVy-=0c`3b9T6?)_cbphBSsex}wo}Z4$iNt`Wm! z8GuZLCr4Fb>{%|n3$F6T@-mhc7Oo(OzP+hk52AH0b}U$VTtl3SOf=1A zsbZtb?%>pkG`|YcSY99m#1L$xk!TiDxKNl?Y6{Dp8*lL&PBWG^7BN;a7BEQ`@URJz zI=w==+)O28BagZ?IaH5L@vRUBICDY_XBHPBP9ogFMlgraHkQMc3EOOn@|{HRITUTe zP7dSwrTZe(eRzyJFbR@}(gI8t73GVF;!SG34-qg#P+q_{EM7umC>qXymtWDsO{AqO z2mk}Ib;1=*P0d=))Le4Mh(lLM+zu@y7H}*|FqYW4vk9b>#^BdlqxzVw1Sb(ukRO~9 zx`Jp@m`kv-T@E@mRrBH5xa1zd4Yh)w zru>PMNfbO=UIhs=u!00DyCAPCd!%yVm13bGISm#LT(QEr^twr8akvRyd7yA)(859B zH|)w;T~O4+Po&6aI#xMgWiwP()-1 zdLZ<+sTlfYx~eR)wyiEG>ETCk#^kkXFzpmr2%9TUhyrZG?E>v|Dwown9)H3R_|Yhl zA!M>DP>P!I6#a~$egBG~uzzL*AM(F8+k|B9hsrR$;BK~Run%of6)rD~o& z?%@v)Im|O3N}Dxrz{+K9WbYfVT%s(%$-m}EgOejwy>I+C98rJ85%Pyz zrcY4dKa+%U_ae$f7+Lc{h z8_e!T=y1{b%F}QzcXmJ4O6M9pzv7*-UWnb5Uz#o`qg1Z{s*5?x9G)fNU6EXRsFHJz2 z91KV=_7chxsDF@O1}mEXZZIIe|79!)KA4}z0>c~6uOG;7=`Zs;%E=N(dNcUQ$mIN< znUr50&iulc@cAVMgXR~$G+qU*jGqUCprZiLFZU3LW^yp#C47GWA7Vkkpx%kb$I5TG z3Ns;+&)z>wjn{ZW!Qo+ymp1=JqdBq%LdrTxpMh07XSOqF*zGXdYx?tf5}DJq-LW~I znec&O?O;$6AgRF`&tY-v3E6?-e8F9cj!H7_YaBMclQlGtO-89gg-ylny4s1$~FWBZ8Fo07rgmAEXXg5x`IWAI$G z8`n!#A;H0tRTwlHa)dMXd9Uh${`slP=)oh$r znt=%7tXv1jX)@mZl1bPN7+w277M-e#y(M;Opx3z!XbfuNyAnJ;-07*$Qcrs6cAb=Pe+zKMMzFh7 zV=iF8-(vpgMfT+Nspnk9HQHrS+y%xef_8axsg4}GvgnUmJUgn}f{2M}d!11sz^a;h zN%d_yDGbyT+mVPi8QdO#B%>vaoJp-}R=E6kJ}^5W_f$#X#svBkMJM7MNw?vPyquV3 zeOTB)!-FEaLNRd@F}XMrFd@(h>YddtASek=P#+-Mo@}d}9x~>lRJZn?ERUtrR zvI2F^)qT`s5 zVhRfslrRtqde;I;m?C0`lcg+F5sNt$0iELoagv}t)CF|Ty1n?+gPg z5Qly1T!$};5j}zCKx2eRvag9KPlDr^ehO(DCke>i)1f}>fdU0J$rUVJg-M`}bAp22 z$3X#1P6U-hkw?iuvIJPY5eN$n7-2n`W03%zvy_FFWdWxmpmUtc?@pm|=o}{q82%(d zz)YZmK#UU)MAQQ9l@L6^+%6Y>*-XI1*^M|b&Eq6N?Vw1v3LX=|6T*PKCM9eVs3}wq zz2iXb=LB`o5be9@jVo-QE}Q|QFmavcEy5{@yOUI|M${hk0iEMj4#Q{Pl(Skn%mhmi zT^=bdp1%_vfz*caETmHrJf``-#`KZcKGE*EMzLx9oyBv;^K*>(u11YfyiHYNl- zM+dh85ES%|2NlQ(DjdBqU{8XyLI0d0VCWp*YWO%60iCl2fxwH;V}kZjK|tp?mBaXP z9Trv+nh8u054AsM`B{h)Jb~PTn>xb?13aWq4oHZ_WK26aNqG3g=us&i6wwuWO;E&v zf|!aqF+uNmOi<(q>p2>@V}qccia@r4STh!w5;!A9apGFdN7()+wNL0Ar}BqH?V*BT zi5vk>LD9Acp(tLabl1ae!#1?M&F;RVW*&aW}`b9T>}$Af~?C=nFL*f>SN&^b$32s#T#;3a`60y@VFLVaxZ%lD+@B#Y)IN47<<4q5uZz#=xk#Oo`X|2uuRH#K4UM*pe0LmrHz1yKIq_lH zk)F>-w#*#7eEF0^-m)?JTe0jN!*Sib8){p2XV)QP1KF>t`|`xR`yBFU_4nl?1|F6D z81B%u_f=2(UZLJSr2C_E?+@_j`!$DKvUE~kJ=XScpHKak-Tj32F0x84dtcm+d+H(2 zbdjistu_sYS>mGg)3Ww_&}}es`%$$Xyy3x8uG+eT=SNCvxL?`4w!+XMp;qq`N;zKs z{OR?1WtqO8H+ZaE@ML?bn&`BlT;Kcj3g3^FaeU8w+rK*Wb`&OUKf3kCR`2ZcdYkJb zt=FnsN6nWQ79+ZCX@Mu1TbJdnzkF)I`_(e=`!9}{Gy-dM3O@`EgjzVpYcMKx9@n;2 zx@OqjJT)9zPP?cPQUBod^P^ufsujhbiN~+iZ9ZjT_u|=SiNdc-Zg^*`u3z_EFmsdF zh4eRFBi0Yk^zYRb8EFw32t9D=Uc&~rEhZA97y4%M&FETnXz*rlT|xF>U4e=C(Mu1E zI=@HP9MD7__abFhvm*FvlpKAU(=3#`%TBhWUUUrK|3>J#I^$-Z4_E4;ukRPB*MyEp zFG;cWZhbM2S(dl6tWROysD#7L++8&9=B0f%k!uZHZ&taH`qJW%&TrB4wZHYf+T|bR zrlmkL*w8oZIONp#F~V=a?seBi1)T#I9CQ@tRox%397C*|TmDqL(l>f^+o{jnOJ|y$ z+g0e-(waKMx**p!-rIJ}_IABv))D*ey#|LYeK)4**X#-`>}p+7=eO;SnzdBj&CBsa zLsvw4hmL<$etST@b})F@HFLOs_u2FxH$J52UadTMPnTl)qb+@lTjy96@@QD7Ii*)O z{8mJRU1P$26Dg!~Z1~ycBUz($04!4$St@_TP zIFqq-AtN27tWJlPwC$d`8@TclxWc4?57SbC`?q?XR5m-ykw z?|}0|20kRK@QIYH5d=_*gyWyRhYZDS!M#wDs4Xe$6 zNl$tgW;z!5dUR(Y4N->t{Ksri;Ixr(R#uliB0$TEwQl&U(n$lIaFScbu0#d38Hf9i zpdnM!Z>Vm5HVK~wHUK8!7s~c0J(^_VNg$EB(}h+^!xd6G;+M2LE{r zel)=rN|KEYtM|ayE68?2z7528% zJ+nJ^lJV}xiGs-EW*js&bW@+k92jvwU@w zbg%fqo10?Q{=?&N;z}XdF>&5Y;wt9qcO`z;HPhFX80|#Nh!Npd&m6~s@9bWdUsL@w zTr82WYZs0x@`3zzs`hL52orp-)Kew3s+Zb7u7yOsbJF8 z8jm-?`EI7~Pc3V7lTkTsKhAC@9c|don)|93dLwD?XzvWWwM^7!c9L%P@@lPMNz&73 z_vT#PK=}%t4?5oyepYqyqS6$bf2$lfmHW>d)(X0L)8xiZ(THouqQV7O*&Nau78)O$G4+6%1f9NXjPP z<|l2fu+1p3{vY~U3x0N*?nes>YXf@(8CF_uH-kdwEs6H7Y1O7$57UlYHN&rZHlN3(_&#=Q^j#!*-*dd42Jk0@hlJhRO@=-a3r)j=es zidG1)09&LhQuitnMGcL6cvR*=9vKKHODW}x`YlhxRy}YUhR<_~=tR;qxJI${xjV8H zuhtKahSu?b_s7eON9lw6A?jjY?a$&nvN*4>Qh5R`X~yh!7xUi=LSNv9`yQNT)ut)s zfPC?}6ob*I&vNai8ZhUUY(+0)L3-==X6^L zhZ{7!<>F(o0}6z@=fx(>d)oPa_@4Wtc2WLus(#Af*K_R2RdNT&?W3ceF|j!(r@NHa$KwIRbd2R)O`& z!y((VocQS)3!2`0KD7QrIVk64X$jKUC)RHSuA3O^0-kMOgi9$c3hjFi`}jfh_s_kl zj;Sx-J6(E~uSKrc-}fRAC8Qp9-uJ|tk@>Y2hjQ+q@E3ZJ|H%B&%7b;89#BNm)u&_M z!T~0-LOtNmm(#_v)HhM{nrN%db1}eo;|h&uK#|^}sy#enYb5$)GNhoKuz${{(W|(i zp`7nHtLwu1XNI&B_G;Fu8}vqA|J=}NwPi|d@7tDXZw8o_+5Ib}08wZrZ^E>$2s>YA zUTp!#6-aNRuF9=5!Nxhy;j7#-=-|ll$Y^LaF?K}ETu?xPBPggyIE(g&p+v{ThlyKX)gxixy&;eg`P8{IujoC@0Buy6Y_Rr!S`; zDY-)~*4QQ;FlLCkiXKD64PX4umdsC~2<71h9To&H%}_q~(R=_fIg_|{wqr1H=y+6# zXuj{QKL1ywA+)G=Bi^)w;&8bA>j_yv#lv$S_d3nqeh!0 ziWyTV+ZqObf`-FWSD_i>d&kDUuAHI zMM(Pdmd`Has{x;}35cnRb&Cmks?MOCQr1Rrk#~IP77sE*<9YOpXyPAMHa;YB%RpM< zr-@Rv#7~Qf_H$1-4hqkI6*W4*PII@GFD%{)=Xj>2&=l^$pJ|Qr86YD^K!XmJ_LRq6 z3BRddd_%#}4dB_Sku;7?Gw|%U8nAru9&@dr#0hNcKCry>YWe4Lk`%{-avOc+9^xC* z<@W1-wqCdw+C=L{O79s)g5}1vdqwQD%l;G>qgR=~9TxTX!nsF$Q)4iKiySqOo3tO| z=CKo~uKCHmmRhOZkXR&iGMme=;x1an@-GagNl2~Ys7Oyr!6Q}D7}vg`d};P4QXz<4ArtcUwnuyUo@Lrr=#Zy76*=E03bq-`22ovnO@3jOXK$>X5Z1qYsgK zbA{$)RpFr3=C!WFm=barBR0BTjab-o7fTn5vST+@;A^j@QmJ!$CDc)#72olZG)`JX zZL9}7N7u+s+iVNVzZ{r%Cv1O@N~!`{uGVtw{4@-)Q?3v_lia^5_GIMPIopI#hZ>P} zyyfZ3PTrE!Q`hA#5v+UDl?kgW{E&{vn`j@+$en4(`1i`zVb*>+yXtl)p2=g@4qbK2 zF8Vd_m0M#lX)IoB`b%HE5|(M*D=H|o$}gh^8XLa1fXcxjE8NzPP(cn6$$&-eU@B)o zDNPZ|Ua++Ygzon-eJOs?eiNDoK2hkQ@HUm; zw>6!n5$c3rwy_{~y4iIt!Jj;jX0*Iu_D~9Qqg@fI{QYDZ5P8d)+!W{dX)gUF%tWx} z@AXZdU)&c))?HPRQ4d%OVO5)C=6TLnjq7*tlzP&`bxfjp#N+^N9uWQ5`T=B-egfL2%SoTfUMB0$?>Kg0@-K^5~CFkBtV#Q&& z$8whsV2^3wH4=nbvdJo?ZJ@N#Yv}WzqfLwaTu$noe+s`yKa^37xh^zjj=(|j2{Qk_ zaCK6T)}J-PeY_x}AiecYNQ801wyba<-e5YsH(&evJjvFQqhSQu>CM^N$m~g0qm%mg z-P5k+pHuALa5bZHR^8BbbfCoJv$w@9y?FHMR%s1AWwo1yRzmqB% z3vX#?Xs&d|eQ2pEIw&Uk3@H|gN=o=%n+An>rI(W?$c(^NcWuyhIf*a97=w*zQsNoX z4-Dz=%RLRr%bHnhBseTnp{%|jOC&DH9uBWx-MaS4kArmu!m$1Ui!^1LCfx$4plpAU zWs41utL+&Jzu5WQ9pd?k>aI)k3Ea_;sBODpI&nnaWhSX2RZO?}Jn3inY(`{CzJU@9 z@`-0h9cD+7F<}a;mUuc1!5RVru!%S7-H2b&Al-z7v?A~84sSCFyQo%&5D~U~pO*Ah z(tXL}oh9l^N#2aewCEZN2Mj#b7&R(VMmG-vG_7ygYpFo3rG_dBsWFYCVZ3=exNRchy5AUR%!jABhbIgCGgU7%0Ubv2akzv0+ zu7yysyrVAh1mxs1@J6Tejih{&OKq3cGAEm)9x8b+_PVi|j8#m?bH_3CBaYqL5F#E) zFT^OI2A3iT76cTUjwQ#@*4tl%uw9(v>gq6`1avp!27@eiqW&1*}TMN`~DJdG^mEA8Z2zLh>2*9NdRh+-ydddmb5T0g>&D(7SF8I_Cg zn2j&~I^cDI^g{5P1kn0|^;~d`5hLi^$`S^ViO?R@@w;AY8(0p+o)w0{&hGJ~2(wOZ zUdjLV6I_0b9_3LMS)ft67jo*HJn5TqJnzu36z(mm9R;@fI-q!{oIjE*Gz3tE=cm2r zh*BzKBZ|`HDnpN-FvRqI9yp<}pG>EbJMarcfA%AgEC?)6_)^NarY^6=wtLX9tA3nB zC)K)u>RiDXOtpBzA54LpU!Uw=bEbleLuc1|Jb7Zg^?A!AsC-NeKh34;h%haTjgV+# z<(huT&FRzF`eM95OhfW#Rsx9Ktl-6t4P`GHTueEnltYiRdh?E1c27-`CW@7z^4axf zo=cHvXWp0jCxk!Mf93!=Jc6Ts8Ppmpd|d^Zv){Fs9pj#_OmTcmByy`svJ~LPv?D=Q zk%%M%*Kju1e#c*l?{__nEKV;|$_euKK0E~RJnwzp%QOmX#Pihh{9J1CrwNboCsA2)u~yk!y)MBg7HNqBM zy{K=#%SUeYS6LCQsFtO##^qdM)ELmX$q%$`O!Sp)R77ou8hP(s7wMNnO@(f>6$XH* ziBP`ArBKE>Qe@RsD7gU12>4>}_nr>xT}#*_2pjJuUW*x|+y2GU|7xa*F~q=>8#=CYV=DC>g79ZK}pN zq?wc^XhZeVc=603t%bqzKKujFzMn?OY}8$F`K8UDw!}uw<^*yvmGfH;!(vuz`(Z0+ z?#S(>1@&eAWbH>spl0**ilrq|N9#{0vZ&0SQPHeqYjAw*=Y^E7p(;`l>d__5C1weye;Uuuz3nxtTyM0^(EZ3i&zD8b-0Xd6N|eYQ92Vn+X(?!Ha>@xK(zs@mf(M za3)#K(uPfQDqqqLAJ3GqtrGIk1j^!`GpT{zT5BL-__9|5V=lQ~H1j_8L7!=ZH6&(S zwLfIH|$M=+m&^B(kgoSr*R@wTZ`A%P?Qvj_+-b-o>;=xkH?zH zT_y!OuHz81x9f@tz5$jTa5{|euZOmr+|{m+Yv$E6o*GP5W>^=CUv&@j+cjX;Y#Rag zi5W>1e7z_{!4M`&_icGg!!mCD3g_Ma_s>&4-;*?km2V}O49kvjKsQO~sv`%WL3CP2scx~MWa$TRME{h#k2!gi3Y46 zG>jau$_1y#CXyLHRwp1Dx*MQ39F)$H1&gPrbF2(8A3JdA5NKk2ZQY+gH0l$YZEYTJ zdzmKp|rL3$%Z;huPzb2Mcbz7QQHtl9s>}Ehh+G@#C!5V7w^=nj+74vQObtVp0 zp|AhMIFTtKgFF`J3mNjAr^VOVM41`>p~SaaZ`n?7n8U@kj+-T~p@ZQQK4T()1X2fP zCU)Qloi4lhv}3et|Lg{R^1-h!iA%C#TvGf6;Kb#EP$ir??Nnwx=11b~gqap-IPcLo zuR(j9Zi@T_Yp%GEsHl10t;50ew|VGdCWHD6EyXVtUwz#8nkY)$aaTGCG=IK-_x5$d z8wgHb4ZdC)Nq*NQ0BcdEOwCT~YI3pSn)|`%RzZaIuOToiR1YSRH_o zc1bvkNKHaiv+P>zNM}aV;oWA=0;g-{7N1+^GBx~H>Hp%bN1t~{BpDlVZCdhr$SFyW zUWUq7NUeFg$3{W8?nL%Ad&MKbxbff{sJ5Rif9x1FSmBgVTK{WYza=E}ZVBGA6%IZL ztbK7Sks9NSYxym%!BKEOIMe4y3Om08iD!ElsBI;$f@aspO#> z66s(B(Ln;f`~&QS2_a4%n|nfr6!olXnmv)3u`X3=4cLJc12R-XhUzB$xMn^qL~;|; zro)^rBikynn?K|-c0NjVkf62ZX1U6%Ki;iOAI+VsV!3iK+AFZnLvp!X6^w}W?LZ)g zt!Wq^%C6}xEz|oxn$`A4x;*wOOA`!vJjBC&ks34+do1VkygI**!v?ZtJ6+Q@aVlpK zfXfQjs&!Ct7x!dfUb9*Qf#89bb(OQE;Z;SQkc|#`A7*T64uN z9mE(3C<`f3EZN{FNFjOnUu@VKTYCve`+{5N>a!LVTVgR@h&f1U@7-G0v7;esRTKR0 z?RIQ*s^z-(?_)B_D;_>PSq~?$7Zs>bk(?>B{cK1bbH-5>4b;tV zSQXsa0uZM?@yrK|5x3Ll`$buqqFde zHK2sVm+Kf41!vYCN7t~^k~MlBsM}^~Vxne@w%aC9t8T5jRW+%$9nsX}l8)!0xq~z_vko7_qo;uJ96n6O@!H6=mL*?Un@?CGFj{f>IDMluJ-|)<^m&**moHv7#_O=^69G+8KT| zY`0^?5iZ-gzTv@W+@2KPnF05AaXc>bN}|f|NIKz zRH|CUFco=u7G=jlOH9|zK^3*4o%I^KhjW7c5y}G_Wcq z`|~^Z%9s#~I)~-HeP_d_$onqRf3`CVh6S}6ctjVeX=jKE976Bkwa+<7BOp#Wc&?|u z4dA-xJ;{6MGui8=hTUP!7s`2@xxgycS5uywc^)eU+;c*^B5)XP1@KaWL>^+iF=mPB z@ls=T<3l>6gQ1?6dU}!-7jalvc8p7l zbPYE1O$&hn{`4&AKZKY|s}9ZZq|$&Sdk#)Jly!9q*O+C$M6DGrSVv?&_wQZ*t6yH_ z#gd?9=~=4W5(Z*w%<1XoTABghe!Deo z^(yJJLW~AKi*T8IDQ)QPpRwuEQi1C1`R`ku)SgG16{p>cxwItYFoOJBQ*s#j6Up6|QILVZPt9 zasvGEgoYV4J#u$I8{qINzv>m{BTf`ZsTc^2TjsJ+kV%O%fX@_5O-&T{m_u~>1>|0o zJZ!Ti(3}d|`M$=UB4yeBj#2u**0x71?;Rsr){%CJ-Gt!w%li8>R_6!6mtit<+xmH$61?exLdi|;ErV1+U__* zI-@OItR4Td{f&hNbI03q_25@_S{oJ#iHj>an6-xPYu~oaoD6^GFw4*krmSyW2WHtb zY!@?-7&YS9MNyck_oo0b{qNctt;~ME42pT>NNmhn8jODfL3XhTv*hnyO#ZU_x^Nnx zBqfE>DMTqrYo;gu>c9?RntHDzRgibWYb#{t@addaf;n=7rpn`!`|N0he2?gfy`s#W z^ep7`!%-3`-S0pHgrODPxQ2VN>Lh&b6PkJWz2xFagd(-9{N|2q+ZCI|!?7DRaDpw3 z-U8~Vdxt~0$I=iQiGM3w9EF-{l$C&cgjZ687ZkBuEj5 zYhwWd#r1OMS5E^3Aco5i=FYW^HZKMYZ1ZciZ4+?&?k$#eC=O+8`MuRkrf)9BE}8tF z{0<}(Ps)2HjBT)8G?@7UB`u8|3?6ThD`oS`yDg3Qv;w%w>&mBEzX6>u64S_vjIulw zW_vTA{FMIXll&o0pXgaQPcFIY^n|6TC0&@4*EDX>-KgYtjB$&gBrM# zw_P0CU$?S*)5qBRomf@CH!wjXr!Aa4obUTpJ+oNMrxpLKGBIMAOHe(9fw=%G|FY_d=e#@+JBV#VSPcsSj z30~^JGE zqg3r<8aPCKjJuR?>K6up#kk)yiL`DirA7!)PtAh5kslgxKN?g^n*C@t#xXT?n@2RG z<>h4(0Fs68N@k7vHWTt3HKzJ0M?qi?d%N8#g)-?lf)dC-H2F4UH8k^^?3Y;5T!IK> z6fQP+KLH{TU{-_#eVDYDSsYT78Wq1l!!uhezhjdsDmK(@r^JXxvTfH}K!t0QPF&ST zAMmz`ZvSRxmEEEVf9=&wBjNGR_gGBjSi(FN!27lNJg7ic6i**2_~@3-Bqaf5Z|Pe9 z6g0vbFY28z>Wt$%sICUFw*~lo5FvkaQ`ybPv%vseU-l-AnP614^Wt=(ex?CHX)nn> z`njXw)jv7GuT`CkVdB6)?+ez;mQ?NVwWM0>+Et+Sbcn)0k2`{1(cS?*Qon4M6F4_X z>w$R|J(wGzVj?1Ju#{Y8F z^04^$(_bMJZyw3BJoE>$T88D@i|M5q@^fuN_hbs$=IYCJPMjd;c@A0+$5_u6(YYys z8gl=VL5hrAk!`Q40O5vRs!Rew??7%7e)QaA1PxyG1pyz^VD1)&Se5!8ls&gxZeT>z zT3j>YZK80#!%7`KgI3XIug#?98;S+KoZ7L|xmWfCzQu%qckXr$mR-}cct&W{goa(y zE!VdEDa&zpmg&WOQ+#WTKT^CVmQz*H6wFhJC@a$}ni_$a+Ss&gZOx3@MV3~{#~t0U zX{$W^Z$8uFt6u!3dc{J_Xj+unMcS5*#5QF{=V!9MMs=H8^E~C0Bs8wf5PHr~4p2Ai zl}@&T06%h9R5G;LOfU0~zk7kqNKyIOb;v918)(?tY*F|Y^{WB=+mw&|R$Wky{sXM% z6Oh~I>knz3Yx0O3c1+*h$zf;#bf|oKh$@Zn<-E>J;=z13wO*$MU6P(tEVZ|tSvD`P z4^Jfs`P!6s<;$HClzJxj#+T2CVu9Pd(C`DW-5tG~eL6O0es|uW-MFJzKyf%iJI}$( zizlFTsI>Oz=dh2PL-V3~`Kr@KftAP>yQ>R4$U8jdBW&ngp&yAUN;qVyZKy$P;vcdx16dxl${3h{E8Xu4hhXE`90 zAgj;niQnTm0r-EufA+R!C((b&Tv{{hQ;XN3kx(uC{e)!(45lMCc^nhbHATDYUl8?0 z7T!%}%P{Po)`ReK9@I46Ar&f>8o9iuL}$ZcbNaIBX3bY!sT0XY!lGqgQ4}(laCHSJ zP)-I*XDtZCNeMS5l(@ zN3S`9<^_I7*N|5XKK$3ThG(l=ne|rpwB~k2-^`qoN*YGIGQ6_HDoXk?YQWPstNZT5%RSyg5Iz#+-HK?T5K-2ohPIpmu8b18e%!#V1mg#%;}k4 zfPOr$nfI|&V|9{swK3N1%)ZT@PI}uX$TfyF541XO8ukc9kN(TRtDwB6=|4oNb{4~D zzSHOF;4Vy9!gwZU2N%P0|E~Ro8F;pVG|C%&w1t)Tlx)iAygUO8DAk5KjaaLVXbRNW z*UGH#_H0ps6L#O9PUp1{PE|thsV` zgNeM1)H}WlRuuLjdTSfsOEC1@)Aswh|GdA)za%m1b|5g(waSI(h+o^S5k8LP zr3$zxOTIa{e4xfVUH}~cSj656L4_slAzTb;bm{G1mx)h2So+&jL+| zBFmar^XAE-^8I;!IT3h_Bra>AipPr;$$kx7+rJ{W3hp;m+QIkomXTsF3#~L(!22tL#AX%x;)zV_<0<}{Hnyx<$|Z4F$Uq9G zz^^=S|HW(+r!3Fg30zxKc5;)IR=4X%uRv(^8E#;&Ns_ngMQ>TN{P@i=(Zvb|Qr)V( z!yy0zxRTomm*of+GNXEuf{{l|bDewcvthiauiB-X8V#B~gOPFrMKf*}Sb`#83w}IT zwgg@Omo|PTFT&f$Uh=hSv6+9pC22UWPT1OJP-(;#96jcr(K5j#AzW`A?4aW*xG)~a zaeJbt#FpJiJ@X?5nJ@x)c+Jz{yl!ivC9MJeh94Fid;fd$^ALi5v6{rp@^iP!;mv2A zyjwvv4HZBBH#RCMQ6IjA^2h4E5|$e%y0k18Zfn{f29~;EK0!wvH|QU;AAFIgY7Q1F zZozTieb&VCn`{N;8g+kb3ez$2*=MnAJ_cIflkX9`cVu++NzBDr^>9u(5}0?8w4m-T zt|nujKDH!&Y%A2s>uSqdI31}x>RnZ$l2e%mdYi8?-8(OGFe0%RWf8KY#ukTt(c~WUW5Ev~lug)^QYQtd;;EU9RS5s9_`D>8O4Y~BT7ML-tx5*9muHBm z|DG{-^JypC-r80_@=~28Sty~Z^)eebt(}QTt&pbrys>9#O$9?DS99k059&O8KZ~yS zlH8pyP;usP|9B;LsjpZ)9lvkUK_!TVdZIp=7K#3*Lc?^P4MbR^v`?=4jXqfNR+4QF zdU?t&Xv3!Ae2ikn$)66+`+%dAFwTwCVx#x>RoV`h3tiC*gYcon2-G%jX347OIIP2C zJ#jgs8C1}-bz+VS+XWNNUI=zt4S!P-b$6;W?ce^BJ$ zAHkT7F`oV&m4rp#bfT}hz)LqZDvomJHMkK5RGG?!s?YVka0UP zLGpuMHMy}UM$o^}a;R{yX)#DmU6>Awt9e>6_~>5(qPk5$=B+;l*Y8oixTQZRumAh6r;wC3==NzQ!@{;E)dVH9@V&gI#fT62Kw>Ir&KUXajdV85_I7}V4U6y+DZ*o5R?9@*nh>1{I zznBIul^N8|@i=@g9^V1ar9D@_3*L{`9Sp!0w$tlu@h%ptMs_>C|3WQb%#+?O#6Txd zri+h_$($n7>M)3{N}8$I#g7eTEAp-;^%5x>ssomUXK6 z;tKwsijm5?f={$cz17a3Xer#FhFYzFAS&8=Z`Y}KRn!oS6jz6+1okcm*+UaoFhdKT z4pIC%8P@aBqHv9M_ADj+rj1!pnj!tyvC|}m{ZAx%N(wgqM+GXgh+F% zb>+|P3WW0hqpzNPo-UQ1;n2PYTYl5$e36zgn$UYFW*jUL5F!48NbzDVWKg7{##XcK z9UE{8J+5e$+!4#-aP`T(#?N%KKdX93STiZQR^rB&uehk>&H~=mZ{8%mOn1T~q2^EgZN=h)_+P;&1Kvj(B1D~ zTpulsq)S+BP+O4a`~2#5mZ=HdCj=K%x~?akRWo(^X1jmF{S>8fG{3)j0~q}Unz>PeenDJ^7#rLThtmXej+|RxL0o=IE3(dxr+X z@YUQ@u2^O!zM=0IJgjfN5<(eefvE7knSueVdBHXA6{!#YBesb5+8d2H{zLi8a+^K# zIh7jsD$Du#n;9TO4Igdt;SaKMim%;hi{xHX>V00CQMSffRmbFef;+oEd1oj$ARP~x zoKe4+ak1uP;VI4tX53p}*4OndHK6eNR*O*sUsp+^<*8-rvBbXVnIYqBCwx?_Gwq^y zU=g&)k5L)hvMF5HiF*GwFTjKGeQea8i5FTtR#L53(z9#z+t1$LG9XOP3v zzWbT}pzY8dzL}pv-QS<`e!d-<$}jzi?(3fo{9@3kfI@F|X{(S3yOrSf3K$qkh`c(( z+9XXcnP9ukcY|H7xIh^Uvt|kh4eT!n?NnBUxwdIlgWN!u*FIA`{gJn4Id$^pG7%!m zRKWIvL|fq=YqrMWQko2&w-oZdw#41uKw@$Yd!@38DO>r~_J;7jARhaO9jcyJk-7MR z^w0j$9Qi(v2uCV2_(lWtBUh-HSJ_L;r&*joMkGZZrW(hw?t{{#?mWM?0%gMIwqU!VUm5bIU+?YSaF2k+N4-EP0f zAt{Ce^>XfImB%D7IE4^lLd~}d<9~qqh8L=HF8vehf`Pg0shr8mM0PT_ut!^eMV(d4tVA!DW&qDAXtwfa#n5euDT!{XZ(MZ~g{VWi=> zWYYEUHL;XxW!n(W*c9+g%1r3Bb<1uYWeKjOMca1g%TfJ~F#LbhAUIUDEBMvW`b{xP zcP4{t04l-M)7nSTe==>NhLMFxhu<^mx2cWWdvH&GQOF%%Y3_sj^TM*i){W3{(`my4 zTT5^!m_dIhv$G5wAZc8%dYzeJ*+i24&1(~M>MqF1c6)4D2K7zPSX8-*GC!EOUNr;t zF(G>u)(9)wIaZo6*G~Mo|D+#usL`)_n{C#Xs^Tq#7N1YHa@btQ`n<+YEPDUW@wEl> zB{_dYDUMAd&uLA23JE0(3>6|C6HIoy{O>H9M?#-EwWsX07EjaYZn}v_!lu?dm@f*W zQa25_3`W=yF%Bt4ZO2ze>xeOyVm8hl7^hvL=^y;0a1mAG+mlu|r8_|`3LPGuw(i9@ zzsZ;rr&Q1;{<(jrF9M}uC-I+UsnJTS5UYW}r);9?H$o{$&)z5_b5)b$zgxz}oG=5) z$*I0)LLI$`u)bpJ?QLPd7Gj&f%fP>+#Gp}h(HTRgsO%nQYS&L48@fL?fLl{;T=ZBu=ZATu}IOqU}mq@Y5PJJ#fQ1hhZ-vb?@DIyf7@$d z@a4juWxCa0wb;ts7J*Cp`l>FWSD*NNc{=b*Ql6*q$J#Pvvi+!BmSR>k^7n(!nLEGV?S@N-AulI=e?(IIlmP7EgLJB>b-Nqe}52i zKbD`n+NhbMe(87@sp8d(XeG` z0wbDHm_tc#6tN!js!-(kfrsGPb=MHEMB!puvUFq5%L!cPT?-0awvBR2GeknTOSQ+X zqO7;~pO$)2xxo444a|gwsw39$dl=mnoQ!QK|Dn~9rD~Ik1|{V8Hlkw}l}4?(d^7FC zy4DRUE#&*#w{)~a;Bxd)^j{J5KL zjsaI~1?DyTyk(IEYu;!TNE$N=RV3Yulryssd_{a04u=BkIT z`sgKSq|I|;1u8<%4g|7sRN}_kqVg+Yr7-rbQ(NU7?M6w-pUD@WA+Zkv9@I@D6-(i3T`>m>b>0aKJX8cA4XC;kM zvzC}_5B;k~YFf3C?U#&^Ro`mU)(Ym3Js+!>YaytwGo9-vvDYk$k9&2V0}z4$^Cjux z4iBgF?mkm!U&gzdpDwZyH23VHkSYD2p)Jt<|8(AEvROVzsmLqB|9G zce~6Hy0S;JdZi5)?VVr$T-a0K5E>g>X63cP%PsBU9}jZb3Xq~H3fFT`FZ?3+d<}L~N6{w*aCuzn)zen`yq9JGD|!GSHSQ*k6~C!agmAy4+Up-i~Z@!)Q8P zt)2T^Xi6ahFX-f^yhY!D(P#|rKof2WivMlYKod(*>M|9T^}v>u8b}Sz+-hW25P7(a zdc(EXUM%oGC2dkgq+>uDa3&Y2xdFKuuTWPKlhGtvfZxl--dYUb>;i+_jrUuBnEvfE zY{Tg#yuQSCzqpMit^J#*y7Bo)N;qd z40)-94y`#v#+sHfvQgNy+oJ$8L7{zvp+SCQ&!=_z#V<*_6p}&>6^ZiVb571K2;FzL zoaf0Fka+EC!bAF+SW7jci=~WPljes`L+yBReQOB<`3cHc8H0MHY4*RjjEpa?)IXL; z6dXsSyZqpLL0=9Pb3@C!lUfma`$ZD=NRAU$BQjlnk=~UK$OS(C7%IwQ#E)z0E-~cv zq*pXur{-PMw*4e!&sAQlhv#8g{n`#cvYVV1`G%$UWz>(=BCc7Gu#2RhFo)jo_3<3? z$K$yJ94?c(nGetBP(u1tJBD0}O1)RQlY3I?W|C$-T2U80!O;wOiH1zV&+WTCZCg&} zn{78pZgtsE-wSY^SApKn1t>mgvtjjiCaB9%m;ol|%R!pz%XyZSx*9{e>$+SYxe|kR zqOs-bDs*xFdA6faoo%(4ti*@Di-sW7vaR19$Iw zXfYGpgrlUgJR^?OyJv%&tJJ6QqIxPRr+4!pY98p461t!<66Q{>S`N+?I$w7FFkXBu z!-8#>H|TM>|6!*Xs`_6Xl#Zup4hCxyka9XoK=6O#B&VCUg(-2nX_~GEG~}a(N-bNJ zqiC!wF@iR$#&?PT38kiD(U)Egj*T-}O~pmwtm@MATsQ~GdijS=5%U(t#<8J%K%nf0 z(!An=TS3xgPpKsorgItya%Z$}Sw8haqM4I+Z|vUTg!{f_aa%1(vZAJ`qDynJm)l-i zm{JVi`x3>w1D?5J`#!ZYesmU7Pnx9#bJmg7P?lX_nH|plK?a=@;4PjDQla*rWGJYT zTi>}1>9U1qvnkB}fZqWzOuJG7YoSsy_IqLjr@~eg)TAC6Ciwe5oDugpZh6;S_iJlF zyyt5G0c(rD`I2l{IZCd_(#p(s`?EaUG_Sf^wnNu9no6h#Za9iNT5RVTPZrD`^38Y1=g{KHq_i8=U^!Qgr-Gnh~c+_oD zoEmMAB)G3%YN=14{w}kmzYw|%Glc5i{m*tyel*GPA`1@goxhL2cc(F(VpYGkriv8@ zZmMy|&{r@~h28RD$=%Nz`VX}4+yVX@l+UwlGLhWz*t8ikS|iceP;O-WQ4pY|I`N6? z;9Bb3^T_-58_p~es`V=mu?GY9sqIzgA)hz$zZq~pjbgZIDLXG1_=-I?M$-Ax;P9|4 zHIo37=|NUdaHHZkacy4QaIP$xh&1&br9J}6?FfXE-w^b6#=Q>H%5fIq2kh)!$_Cm7 zCNBFVtOq`D;XN+Q3X^{ZGFBy z9e%D;Q_D{%KRC7!_qfeC@LhYxgNOTZ%kTSKzra3BX!n{hSz|=UK6o{%+U9e>Mf-x^ z@t`b~<3Ib>!p-FJb^tL4KFk$mIv?U@BXh(*1$ocvNDeN*TbX>b>x z&wC-=Zymws0$rc^l>0$sb@Wd^w%mJplDF#~r^^j?c?$@Bc+ooh^te?1A#uxv-@`Q< zD9#4ts)Rk?#yX%2JZ zRi`Iq=2tH(v8tVNmshaeo}ZgLk#`oT{_Rm1@~*Sse{%`(Obv%tN2L_;Pfa?`%8nHxl_$L_Xi~jThTkI5KhI>2JJQsfuX3LKm@I#Y#F`tYvD=#{ z8>5GI6R7Cz(DAzL>UK(oP!7K1@6DBSEEMi5Ju>z>qfmMZ)6r5O4DnTJ3Xh`njDhC7LV#MG;HZ0E*-MB1`x;GfC(#4V%Q+DfK0$+ zwbB1^G+CBuW4<;qwruo8QCoaXjAr|=108fhlMs}OXAo&xd1?PPWHYGN3posP%TF4B zFQ3LoR8Xq?&-6h_fnWQtq=ku-lHS*J4ehhwS8HCOx3VwL| z?GI-@jMbonhYe&XqgrhllufeSrEfO%!w!2^|jMkWTuIwq�F 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%0A*=9`xt(_5Le@s_*8b5=|nmS(W zuIV)X3`OW9Zo2I~U3xI!_KSf=vxC{O)CZGapAY$aEu8R6!_a>CrFxhH@-p~{u^{7lD(QERtW|eZnQ+fJed= zxZdmo-&ri`u!WOLnw$P8m-IUD6D7a&&hRC$-S=<>Xmub52j1U%|KU|D;jgUrmacNn z{QeifLtiwwIXJ|aLvk(&;@}9`zbe?*f1jtX?>_heFzl1dcKNTo0VbUQPmEd2GI<~v dnT+>OKNX<@L%9>7z(o#8Cr7CBX@z62iWeur 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 TE+uFOKZUVlqNeS3^wa+URLEs# diff --git a/workbooks/alz_checklist.en_network_counters.json b/workbooks/alz_checklist.en_network_counters.json index 511b0a638..0ceaa54a3 100644 --- a/workbooks/alz_checklist.en_network_counters.json +++ b/workbooks/alz_checklist.en_network_counters.json @@ -861,7 +861,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -880,7 +880,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" } } ] @@ -918,7 +918,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query22Stats:$.Success}" } } ] @@ -937,7 +937,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query22Stats:$.Total}" } } ] @@ -975,7 +975,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" } } ] @@ -994,7 +994,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" } } ] @@ -1032,7 +1032,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Success}" + "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" } } ] @@ -1051,7 +1051,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Total}" + "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" } } ] @@ -1089,7 +1089,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" } } ] @@ -1108,7 +1108,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" } } ] @@ -1203,7 +1203,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" + "resultVal": "{Query27Stats:$.Success}" } } ] @@ -1222,7 +1222,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" + "resultVal": "{Query27Stats:$.Total}" } } ] @@ -1260,7 +1260,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -1279,7 +1279,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -1317,7 +1317,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query22Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.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}+{Query27Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" } } ] @@ -1336,7 +1336,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query22Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.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}+{Query27Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" } } ] @@ -1410,52 +1410,52 @@ "style": "tabs", "links": [ { - "id": "e9efb434-4d68-434e-a3f6-6aba46b3aabb", + "id": "aa39e554-a9b9-4fbd-b262-fed1603849b6", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke ({Tab0Success:value}/{Tab0Total:value})", + "linkLabel": "App delivery ({Tab0Success:value}/{Tab0Total:value})", "subTarget": "tab0", - "preText": "Hub and spoke", + "preText": "App delivery", "style": "primary" }, { - "id": "5fe79e06-8d97-4720-aa95-21c554aa451e", + "id": "66639e47-079c-47e6-b5ef-918122433a71", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan ({Tab1Success:value}/{Tab1Total:value})", + "linkLabel": "PaaS ({Tab1Success:value}/{Tab1Total:value})", "subTarget": "tab1", - "preText": "IP plan", + "preText": "PaaS", "style": "primary" }, { - "id": "92f15c11-2509-4c76-b3e2-aef5570e3f57", + "id": "f1122f51-3ed5-404d-a164-6f6bed3798b8", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation ({Tab2Success:value}/{Tab2Total:value})", + "linkLabel": "IP plan ({Tab2Success:value}/{Tab2Total:value})", "subTarget": "tab2", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "034fb96e-4dfa-4e3b-a155-2bc40b3b9669", + "id": "09f118ac-a108-4912-9f07-f7bf52c25305", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN ({Tab3Success:value}/{Tab3Total:value})", + "linkLabel": "Hybrid ({Tab3Success:value}/{Tab3Total:value})", "subTarget": "tab3", - "preText": "Virtual WAN", + "preText": "Hybrid", "style": "primary" }, { - "id": "c7226419-682e-4c43-bd93-cfc550632b04", + "id": "aaf993c4-ed4b-4a28-a7a0-188358e3341d", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery ({Tab4Success:value}/{Tab4Total:value})", + "linkLabel": "Segmentation ({Tab4Success:value}/{Tab4Total:value})", "subTarget": "tab4", - "preText": "App delivery", + "preText": "Segmentation", "style": "primary" }, { - "id": "62275f9c-2df9-4703-add1-3fda9371410b", + "id": "4f37a079-c98a-4334-a5bb-45a5ba6d200f", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Internet ({Tab5Success:value}/{Tab5Total:value})", @@ -1464,21 +1464,21 @@ "style": "primary" }, { - "id": "e22acfeb-df86-41d3-bff0-dba87cff78b7", + "id": "33ba9ec7-8f85-4525-bbc4-9cb9a10a0c60", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS ({Tab6Success:value}/{Tab6Total:value})", + "linkLabel": "Virtual WAN ({Tab6Success:value}/{Tab6Total:value})", "subTarget": "tab6", - "preText": "PaaS", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "05e8892d-2847-474f-b6b1-1f1adda0259f", + "id": "7ccf030c-9517-451c-be91-78de94a9d695", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid ({Tab7Success:value}/{Tab7Total:value})", + "linkLabel": "Hub and spoke ({Tab7Success:value}/{Tab7Total:value})", "subTarget": "tab7", - "preText": "Hybrid", + "preText": "Hub and spoke", "style": "primary" } ] @@ -1494,22 +1494,22 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## App delivery" }, "name": "tab0title" }, { "type": 1, "content": { - "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." + "json": "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": "querytext5" + "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 == '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/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", @@ -1558,20 +1558,20 @@ ] } }, - "name": "query5" + "name": "query0" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Ensure 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": "querytext6" + "name": "querytext1" }, { "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/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", @@ -1620,20 +1620,20 @@ ] } }, - "name": "query6" + "name": "query1" }, { "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": "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": "querytext7" + "name": "querytext2" }, { "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/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", @@ -1682,20 +1682,20 @@ ] } }, - "name": "query7" + "name": "query2" }, { "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": "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": "querytext8" + "name": "querytext3" }, { "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/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", @@ -1744,42 +1744,20 @@ ] } }, - "name": "query8" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## IP plan" - }, - "name": "tab1title" + "name": "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": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1828,20 +1806,42 @@ ] } }, - "name": "query14" + "name": "query4" + } + ] + }, + "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": "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": "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": "querytext15" + "name": "querytext22" }, { "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 = 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", @@ -1890,7 +1890,7 @@ ] } }, - "name": "query15" + "name": "query22" } ] }, @@ -1910,22 +1910,22 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## IP plan" }, "name": "tab2title" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext23" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1974,20 +1974,20 @@ ] } }, - "name": "query23" + "name": "query14" }, { "type": 1, "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext24" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2036,20 +2036,42 @@ ] } }, - "name": "query24" + "name": "query15" + } + ] + }, + "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" }, { "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": "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": "querytext25" + "name": "querytext9" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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", @@ -2098,20 +2120,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", @@ -2160,42 +2182,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": "## Virtual WAN" - }, - "name": "tab3title" + "name": "query10" }, { "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": "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": "querytext27" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -2244,42 +2244,82 @@ ] } }, - "name": "query27" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query11" + }, { "type": 1, "content": { - "json": "## App delivery" + "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": "tab4title" + "name": "querytext12" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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": "query12" }, { "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 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": "querytext0" + "name": "querytext13" }, { "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/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", @@ -2328,20 +2368,42 @@ ] } }, - "name": "query0" + "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": "## Segmentation" + }, + "name": "tab4title" }, { "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 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": "querytext1" + "name": "querytext23" }, { "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' | 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", @@ -2390,20 +2452,20 @@ ] } }, - "name": "query1" + "name": "query23" }, { "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": "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": "querytext2" + "name": "querytext24" }, { "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/virtualnetworks' | 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", @@ -2452,20 +2514,20 @@ ] } }, - "name": "query2" + "name": "query24" }, { "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": "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": "querytext3" + "name": "querytext25" }, { "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/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", @@ -2514,20 +2576,20 @@ ] } }, - "name": "query3" + "name": "query25" }, { "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": "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": "querytext4" + "name": "querytext26" }, { "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,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", @@ -2576,7 +2638,7 @@ ] } }, - "name": "query4" + "name": "query26" } ] }, @@ -2990,22 +3052,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Virtual WAN" }, "name": "tab6title" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext22" + "name": "querytext27" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = 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/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", @@ -3054,7 +3116,7 @@ ] } }, - "name": "query22" + "name": "query27" } ] }, @@ -3074,84 +3136,22 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## Hub and spoke" }, "name": "tab7title" }, { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." - }, - "name": "querytext9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "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": "query9" - }, - { - "type": 1, - "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "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": "querytext10" + "name": "querytext5" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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", @@ -3200,20 +3200,20 @@ ] } }, - "name": "query10" + "name": "query5" }, { "type": 1, "content": { - "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + "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": "querytext11" + "name": "querytext6" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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", @@ -3262,20 +3262,20 @@ ] } }, - "name": "query11" + "name": "query6" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "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": "querytext12" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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", @@ -3324,20 +3324,20 @@ ] } }, - "name": "query12" + "name": "query7" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "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": "querytext13" + "name": "querytext8" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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", @@ -3386,7 +3386,7 @@ ] } }, - "name": "query13" + "name": "query8" } ] }, diff --git a/workbooks/alz_checklist.en_network_counters_template.json b/workbooks/alz_checklist.en_network_counters_template.json index ac18460e1..9af5b3b33 100644 --- a/workbooks/alz_checklist.en_network_counters_template.json +++ b/workbooks/alz_checklist.en_network_counters_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query11Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query19Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query20Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query21Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query23Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query24Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query24FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query24Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query25Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query25FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query25Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query26Stats\",\n \"type\": 1,\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query26FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query26Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query27Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query14Stats:$.Success}+{Query15Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query14Stats:$.Total}+{Query15Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{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\": \"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\": \"{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\": \"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\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab7Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab7Success}/{Tab7Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"e9efb434-4d68-434e-a3f6-6aba46b3aabb\",\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\": \"5fe79e06-8d97-4720-aa95-21c554aa451e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"92f15c11-2509-4c76-b3e2-aef5570e3f57\",\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\": \"034fb96e-4dfa-4e3b-a155-2bc40b3b9669\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"c7226419-682e-4c43-bd93-cfc550632b04\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"62275f9c-2df9-4703-add1-3fda9371410b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e22acfeb-df86-41d3-bff0-dba87cff78b7\",\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\": \"05e8892d-2847-474f-b6b1-1f1adda0259f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab7Success:value}/{Tab7Total:value})\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext6\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query6\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Consider the limit of routes per route table (400). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query7\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use the setting 'Allow traffic to remote virtual network' when configuring VNet peerings. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-network-manage-peering) for further information.\"\n },\n \"name\": \"querytext8\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query8\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": \"## Virtual WAN\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext27\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query27\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## App delivery\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"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\": \"## Hybrid\"\n },\n \"name\": \"tab7title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext9\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query9\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information.\"\n },\n \"name\": \"querytext10\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query10\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information.\"\n },\n \"name\": \"querytext11\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query11\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext12\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query12\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query13\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab7\"\n },\n \"name\": \"tab7\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query5FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query5Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | summarize peeringcount = count() by id | extend compliant = (peeringcount < 450) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query7Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query11Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query12Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query19Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query20Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query21FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query21Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query23Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query23FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query23Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query24Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query24FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query24Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query25Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query25FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query25Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query26Stats\",\n \"type\": 1,\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query26FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query26Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query27Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{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\": \"{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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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\": \"{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n },\n {\n \"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\": \"{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\": \"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\": \"{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\": \"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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.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\": \"{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 \"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}+{Query22Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.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}+{Query27Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query22Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.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}+{Query27Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review - Network\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"aa39e554-a9b9-4fbd-b262-fed1603849b6\",\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\": \"66639e47-079c-47e6-b5ef-918122433a71\",\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\": \"f1122f51-3ed5-404d-a164-6f6bed3798b8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"09f118ac-a108-4912-9f07-f7bf52c25305\",\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\": \"aaf993c4-ed4b-4a28-a7a0-188358e3341d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"4f37a079-c98a-4334-a5bb-45a5ba6d200f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"33ba9ec7-8f85-4525-bbc4-9cb9a10a0c60\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"7ccf030c-9517-451c-be91-78de94a9d695\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab7Success:value}/{Tab7Total:value})\",\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\": 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\": \"## 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\": \"## IP plan\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"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\": \"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\": \"## Segmentation\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext23\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query23\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information.\"\n },\n \"name\": \"querytext24\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query24\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information.\"\n },\n \"name\": \"querytext25\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query25\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext26\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query26\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"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\": \"## Virtual WAN\"\n },\n \"name\": \"tab6title\"\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\": \"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\": \"## Hub and spoke\"\n },\n \"name\": \"tab7title\"\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}", "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 af487e1df..bbad70404 100644 --- a/workbooks/alz_checklist.en_network_tabcounters.json +++ b/workbooks/alz_checklist.en_network_tabcounters.json @@ -70,16 +70,16 @@ "style": "tabs", "links": [ { - "id": "4c248420-5251-496b-a48e-0bef08626fcd", + "id": "0db4c44c-84ce-4631-9b91-201133edfb57", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery", + "linkLabel": "Hub and spoke", "subTarget": "tab0", - "preText": "App delivery", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "8e834631-89b2-4db9-ba4e-2b11f7ff0f1e", + "id": "2688d908-9569-4763-af0c-e37da815d582", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Hybrid", @@ -88,34 +88,34 @@ "style": "primary" }, { - "id": "2171291d-ad1c-41b1-95c3-964b584fd506", + "id": "46ca61ae-7e06-422a-bde1-49b6a3bb57d1", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Segmentation", "subTarget": "tab2", - "preText": "IP plan", + "preText": "Segmentation", "style": "primary" }, { - "id": "f738e2bb-0b92-49e1-bf6e-024ea79219c0", + "id": "09552bcb-9343-4ff9-b0dd-850a82c4e7b7", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "IP plan", "subTarget": "tab3", - "preText": "Hub and spoke", + "preText": "IP plan", "style": "primary" }, { - "id": "07f418ec-645b-408c-b14b-62d17bfd49c4", + "id": "b39bf91c-0ce9-40dc-acb2-9a57a06c72ae", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "App delivery", "subTarget": "tab4", - "preText": "Virtual WAN", + "preText": "App delivery", "style": "primary" }, { - "id": "e249ad03-bf74-46fd-8708-608b8f2592b2", + "id": "d387f7b4-0340-4aab-b7ae-cb9827db40fe", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "PaaS", @@ -124,16 +124,16 @@ "style": "primary" }, { - "id": "a5380ccb-aec1-49bf-b281-9a2d420e2eb8", + "id": "d1ab6a56-7d18-4303-ba12-0f1187fb672c", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "Virtual WAN", "subTarget": "tab6", - "preText": "Segmentation", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "feb21749-191e-4551-ae2d-06e4c8d3bf6a", + "id": "2c713494-a831-45aa-837f-7b4d202ffcfc", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Internet", @@ -162,37 +162,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0Stats", - "type": 1, - "query": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query0FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query1Stats", + "name": "Query5Stats", "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/virtualnetworks' | 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}" ], @@ -206,9 +178,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query1FullyCompliant", + "name": "Query5FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -218,9 +190,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2Stats", + "name": "Query6Stats", "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/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}" ], @@ -234,9 +206,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2FullyCompliant", + "name": "Query6FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -246,9 +218,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query3Stats", + "name": "Query7Stats", "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/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}" ], @@ -262,9 +234,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query3FullyCompliant", + "name": "Query7FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -274,9 +246,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4Stats", + "name": "Query8Stats", "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/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}" ], @@ -290,9 +262,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4FullyCompliant", + "name": "Query8FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -313,7 +285,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}" } } ] @@ -332,7 +304,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}" } } ] @@ -366,7 +338,7 @@ { "type": 1, "content": { - "json": "## App delivery" + "json": "## Hub and spoke" }, "customWidth": "50", "name": "tab0title" @@ -407,77 +379,15 @@ { "type": 1, "content": { - "json": "Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." - }, - "name": "querytext0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query0" - }, - { - "type": 1, - "content": { - "json": "Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information." + "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": "querytext1" + "name": "querytext5" }, { "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' | 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", @@ -526,20 +436,20 @@ ] } }, - "name": "query1" + "name": "query5" }, { "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": "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": "querytext2" + "name": "querytext6" }, { "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/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", @@ -588,20 +498,20 @@ ] } }, - "name": "query2" + "name": "query6" }, { "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": "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": "querytext3" + "name": "querytext7" }, { "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/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", @@ -650,20 +560,20 @@ ] } }, - "name": "query3" + "name": "query7" }, { "type": 1, "content": { - "json": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information." + "json": "Use 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": "querytext4" + "name": "querytext8" }, { "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' | 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", @@ -712,7 +622,7 @@ ] } }, - "name": "query4" + "name": "query8" } ] }, @@ -1318,9 +1228,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14Stats", + "name": "Query23Stats", "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' | 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}" ], @@ -1334,9 +1244,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14FullyCompliant", + "name": "Query23FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1346,9 +1256,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15Stats", + "name": "Query24Stats", "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/virtualnetworks' | 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}" ], @@ -1362,9 +1272,65 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15FullyCompliant", + "name": "Query24FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query25Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query25FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query26Stats", + "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())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query26FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query26Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1385,7 +1351,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" + "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" } } ] @@ -1404,7 +1370,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" + "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" } } ] @@ -1438,7 +1404,7 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Segmentation" }, "customWidth": "50", "name": "tab2title" @@ -1479,15 +1445,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": "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": "querytext14" + "name": "querytext23" }, { "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 == '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", @@ -1536,20 +1502,20 @@ ] } }, - "name": "query14" + "name": "query23" }, { "type": 1, "content": { - "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Use 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": "querytext15" + "name": "querytext24" }, { "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,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", @@ -1598,7 +1564,131 @@ ] } }, - "name": "query15" + "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, + "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": "query25" + }, + { + "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." + }, + "name": "querytext26" + }, + { + "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", + "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": "query26" } ] }, @@ -1626,65 +1716,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "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' | 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}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query6FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query7Stats", + "name": "Query14Stats", "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/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}" ], @@ -1698,9 +1732,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7FullyCompliant", + "name": "Query14FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1710,9 +1744,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8Stats", + "name": "Query15Stats", "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' | 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}" ], @@ -1726,9 +1760,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8FullyCompliant", + "name": "Query15FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1749,7 +1783,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}" } } ] @@ -1768,7 +1802,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}" } } ] @@ -1802,7 +1836,7 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## IP plan" }, "customWidth": "50", "name": "tab3title" @@ -1843,15 +1877,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 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": "querytext5" + "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 == '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' | 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", @@ -1900,20 +1934,20 @@ ] } }, - "name": "query5" + "name": "query14" }, { "type": 1, "content": { - "json": "When connecting spoke virtual networks to the central hub virtual network, consider VNet peering limits (500), the maximum number of prefixes that can be advertised via ExpressRoute (1000). Check [this link](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=/azure/virtual-network/toc.json#azure-resource-manager-virtual-networking-limits) for further information." + "json": "Ensure that 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": "querytext6" + "name": "querytext15" }, { "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' | 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", @@ -1962,149 +1996,25 @@ ] } }, - "name": "query6" - }, + "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": "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": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 9, + "type": 9, "content": { "version": "KqlParameterItem/1.0", "crossComponentResources": [ @@ -2114,9 +2024,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query27Stats", + "name": "Query0Stats", "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/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}" ], @@ -2130,9 +2040,121 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query27FullyCompliant", + "name": "Query0FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query27Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query1Stats", + "type": 1, + "query": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query1FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query2Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query2FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query2Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query3Stats", + "type": 1, + "query": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query3FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query3Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query4Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query4FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2153,7 +2175,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -2172,7 +2194,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query27Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" } } ] @@ -2206,7 +2228,7 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## App delivery" }, "customWidth": "50", "name": "tab4title" @@ -2247,15 +2269,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": "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": "querytext27" + "name": "querytext0" }, { "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/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", @@ -2304,176 +2326,206 @@ ] } }, - "name": "query27" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab4" - }, - "name": "tab4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "name": "query0" + }, { - "type": 9, + "type": 1, "content": { - "version": "KqlParameterItem/1.0", + "json": "Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information." + }, + "name": "querytext1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", "crossComponentResources": [ "{Subscription}" ], - "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": "Tab5Success", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query22Stats:$.Success}" + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab5Total", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query22Stats:$.Total}" + { + "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": "query1" + }, + { + "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." + }, + "name": "querytext2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab5Percent", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "round(100*{Tab5Success}/{Tab5Total})" - } + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] } - ] - } - ], - "style": "pills", - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" + } + ] + } }, - "name": "TabInvisibleParameters" + "name": "query2" }, { "type": 1, "content": { - "json": "## PaaS" + "json": "Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information." }, - "customWidth": "50", - "name": "tab5title" + "name": "querytext3" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab5Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", - "size": 3, - "queryType": 8, - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 4, - "formatOptions": { - "min": 0, - "max": 100, - "palette": "redGreen" + "query": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } }, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] } } - }, - "subtitleContent": { - "columnMatch": "Column2" - }, - "showBorder": true + ] } }, - "customWidth": "50", - "name": "TabPercentTile" + "name": "query3" }, { "type": 1, "content": { - "json": "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 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": "querytext22" + "name": "querytext4" }, { "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/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", @@ -2522,16 +2574,16 @@ ] } }, - "name": "query22" + "name": "query4" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab4" }, - "name": "tab5" + "name": "tab4" }, { "type": 12, @@ -2550,93 +2602,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "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 == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query23FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query24Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query24FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query25Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query25FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query26Stats", + "name": "Query22Stats", "type": 1, - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type =~ 'microsoft.network/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}" ], @@ -2650,9 +2618,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query26FullyCompliant", + "name": "Query22FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query26Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2662,7 +2630,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Success", + "name": "Tab5Success", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2673,7 +2641,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}" + "resultVal": "{Query22Stats:$.Success}" } } ] @@ -2681,7 +2649,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Total", + "name": "Tab5Total", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2692,7 +2660,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}" + "resultVal": "{Query22Stats:$.Total}" } } ] @@ -2700,7 +2668,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Tab6Percent", + "name": "Tab5Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -2711,7 +2679,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "round(100*{Tab6Success}/{Tab6Total})" + "resultVal": "round(100*{Tab5Success}/{Tab5Total})" } } ] @@ -2726,16 +2694,16 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## PaaS" }, "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", @@ -2767,15 +2735,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": "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": "querytext23" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,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", @@ -2824,144 +2792,176 @@ ] } }, - "name": "query23" - }, - { - "type": 1, - "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." - }, - "name": "querytext24" - }, + "name": "query22" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab5" + }, + "name": "tab5" + }, + { + "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/virtualnetworks' | 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", + "version": "KqlParameterItem/1.0", "crossComponentResources": [ "{Subscription}" ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" + "parameters": [ + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query27Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query27FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query27Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab6Success", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query27Stats:$.Success}" } } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab6Total", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 }, - { - "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" - } - ] + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query27Stats:$.Total}" + } } - } - ] - } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab6Percent", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "round(100*{Tab6Success}/{Tab6Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" }, - "name": "query24" + "name": "TabInvisibleParameters" }, { "type": 1, "content": { - "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." + "json": "## Virtual WAN" }, - "name": "querytext25" + "customWidth": "50", + "name": "tab6title" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab6Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "size": 3, + "queryType": 8, + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 4, + "formatOptions": { + "min": 0, + "max": 100, + "palette": "redGreen" }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true } }, - "name": "query25" + "customWidth": "50", + "name": "TabPercentTile" }, { "type": 1, "content": { - "json": "The application team should use application security groups at the subnet-level NSGs to help protect multi-tier VMs within the landing zone. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/) can help to educate yourself on this." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext26" + "name": "querytext27" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetName=subnets.name,subnetNsg=subnets.properties.networkSecurityGroup | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend compliant = isnotnull(subnetNsg) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -3010,7 +3010,7 @@ ] } }, - "name": "query26" + "name": "query27" } ] }, diff --git a/workbooks/alz_checklist.en_network_tabcounters_template.json b/workbooks/alz_checklist.en_network_tabcounters_template.json index ccee3d220..046dfc999 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\": \"4c248420-5251-496b-a48e-0bef08626fcd\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab0\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8e834631-89b2-4db9-ba4e-2b11f7ff0f1e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2171291d-ad1c-41b1-95c3-964b584fd506\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab2\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f738e2bb-0b92-49e1-bf6e-024ea79219c0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"07f418ec-645b-408c-b14b-62d17bfd49c4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e249ad03-bf74-46fd-8708-608b8f2592b2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a5380ccb-aec1-49bf-b281-9a2d420e2eb8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"feb21749-191e-4551-ae2d-06e4c8d3bf6a\",\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\": 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\": \"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 \"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\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure 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\": 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\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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\": \"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\": \"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\": \"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\": \"{Query14Stats:$.Success}+{Query15Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.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\": \"## IP plan\"\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 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\": \"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\": \"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\": \"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\": \"{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\": \"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\": \"{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\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query27Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query27Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query27Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab4title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab4Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext27\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query27\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab5title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab5Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"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\": \"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 \"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\": \"tab7title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab7Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"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\": \"0db4c44c-84ce-4631-9b91-201133edfb57\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2688d908-9569-4763-af0c-e37da815d582\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"46ca61ae-7e06-422a-bde1-49b6a3bb57d1\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"09552bcb-9343-4ff9-b0dd-850a82c4e7b7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b39bf91c-0ce9-40dc-acb2-9a57a06c72ae\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d387f7b4-0340-4aab-b7ae-cb9827db40fe\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab5\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d1ab6a56-7d18-4303-ba12-0f1187fb672c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2c713494-a831-45aa-837f-7b4d202ffcfc\",\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\": 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\": \"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 \"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\": \"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\": \"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\": 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\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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\": \"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\": \"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\": \"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 \"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\": \"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 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\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query15Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query14Stats:$.Success}+{Query15Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query14Stats:$.Total}+{Query15Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"Query22Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query22FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query22Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query22Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab5Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab5Success}/{Tab5Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab5title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab5Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"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\": \"{Query27Stats:$.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\": \"{Query27Stats:$.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\": \"## Virtual WAN\"\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\": \"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\": \"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\": \"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\": \"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 \"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\": \"tab7title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab7Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"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 374086fdc..2dd56f929 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": "f4366ea4-1a4b-43a5-baa0-36b29f527fb2", + "id": "aeff028d-5064-4bdc-88df-a31017f5f59b", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Hub and spoke", "subTarget": "tab0", - "preText": "IP plan", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "9495360a-f276-4563-9332-a3a494a0760c", + "id": "120d549e-8074-46fb-bbf6-ab0c94891def", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "IP plan", "subTarget": "tab1", - "preText": "Segmentation", + "preText": "IP plan", "style": "primary" }, { - "id": "7567a969-c0a6-4f0e-a548-37aac3df103d", + "id": "87541aba-2c69-4b3c-b3f2-4243137d8eec", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "App delivery", "subTarget": "tab2", - "preText": "PaaS", + "preText": "App delivery", "style": "primary" }, { - "id": "592694b9-dc47-4dd2-9333-319f4bbdb598", + "id": "67224ece-6b6d-494f-a271-f4d7b87d607b", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Internet", "subTarget": "tab3", - "preText": "Hybrid", + "preText": "Internet", "style": "primary" }, { - "id": "f872a398-c4e5-4ae8-938c-f5df3803ffbb", + "id": "55118791-ed80-4890-83cb-2f73c693a113", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery", + "linkLabel": "Segmentation", "subTarget": "tab4", - "preText": "App delivery", + "preText": "Segmentation", "style": "primary" }, { - "id": "d6bc0fc6-40be-4453-8ae9-9eb50a37fd71", + "id": "6a5edaf8-c526-4b73-b1ae-c4f28810da11", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "Hybrid", "subTarget": "tab5", - "preText": "Hub and spoke", + "preText": "Hybrid", "style": "primary" }, { - "id": "c798787f-d2bf-4aa4-a605-3f3635365fbc", + "id": "e924644f-0b80-44d7-b6be-23d1e9026ed8", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "PaaS", "subTarget": "tab6", - "preText": "Virtual WAN", + "preText": "PaaS", "style": "primary" }, { - "id": "20b98487-4573-478c-ae9d-a240da89472d", + "id": "874e739d-01ae-4feb-a1b5-da7099a215b5", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "Virtual WAN", "subTarget": "tab7", - "preText": "Internet", + "preText": "Virtual WAN", "style": "primary" } ] @@ -154,22 +154,22 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Hub and spoke" }, "name": "tab0title" }, { "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -218,20 +218,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -280,42 +280,20 @@ ] } }, - "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": "## Segmentation" - }, - "name": "tab1title" + "name": "query6" }, { "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": "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": "querytext23" + "name": "querytext7" }, { "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/routetables' | mvexpand properties.routes | summarize routeCount = count() by id | extend compliant = (routeCount < 360) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -364,20 +342,20 @@ ] } }, - "name": "query23" + "name": "query7" }, { "type": 1, "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." + "json": "Use 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": "querytext24" + "name": "querytext8" }, { "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' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -426,20 +404,42 @@ ] } }, - "name": "query24" + "name": "query8" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab0" + }, + "name": "tab0" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## IP plan" + }, + "name": "tab1title" }, { "type": 1, "content": { - "json": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." + "json": "Use 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": "querytext25" + "name": "querytext14" }, { "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' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -488,20 +488,20 @@ ] } }, - "name": "query25" + "name": "query14" }, { "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 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": "querytext26" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,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' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -550,7 +550,7 @@ ] } }, - "name": "query26" + "name": "query15" } ] }, @@ -570,22 +570,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## App delivery" }, "name": "tab2title" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "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": "querytext22" + "name": "querytext0" }, { "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/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", @@ -634,42 +634,20 @@ ] } }, - "name": "query22" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab2" - }, - "name": "tab2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hybrid" - }, - "name": "tab3title" + "name": "query0" }, { "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": "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": "querytext9" + "name": "querytext1" }, { "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/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", @@ -718,20 +696,20 @@ ] } }, - "name": "query9" + "name": "query1" }, { "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": "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": "querytext10" + "name": "querytext2" }, { "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/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", @@ -780,20 +758,20 @@ ] } }, - "name": "query10" + "name": "query2" }, { "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": "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": "querytext11" + "name": "querytext3" }, { "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/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", @@ -842,20 +820,20 @@ ] } }, - "name": "query11" + "name": "query3" }, { "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 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": "querytext12" + "name": "querytext4" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier 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/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", @@ -904,20 +882,42 @@ ] } }, - "name": "query12" + "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": "## Internet" + }, + "name": "tab3title" }, { "type": 1, "content": { - "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext13" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -966,42 +966,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": "## App delivery" - }, - "name": "tab4title" + "name": "query16" }, { "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 FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1050,20 +1028,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1112,20 +1090,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1174,20 +1152,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1236,20 +1214,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1298,16 +1276,16 @@ ] } }, - "name": "query4" + "name": "query21" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab4" + "value": "tab3" }, - "name": "tab4" + "name": "tab3" }, { "type": 12, @@ -1318,22 +1296,22 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## Segmentation" }, - "name": "tab5title" + "name": "tab4title" }, { "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1382,20 +1360,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1444,20 +1422,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1506,20 +1484,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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1568,16 +1546,16 @@ ] } }, - "name": "query8" + "name": "query26" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab5" + "value": "tab4" }, - "name": "tab5" + "name": "tab4" }, { "type": 12, @@ -1588,22 +1566,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Hybrid" }, - "name": "tab6title" + "name": "tab5title" }, { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "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": "querytext27" + "name": "querytext9" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1652,42 +1630,20 @@ ] } }, - "name": "query27" - } - ] - }, - "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" + "name": "query9" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information." + "json": "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": "querytext16" + "name": "querytext10" }, { "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/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", @@ -1736,20 +1692,20 @@ ] } }, - "name": "query16" + "name": "query10" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "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": "querytext17" + "name": "querytext11" }, { "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/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", @@ -1798,20 +1754,20 @@ ] } }, - "name": "query17" + "name": "query11" }, { "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": "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": "querytext18" + "name": "querytext12" }, { "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/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", @@ -1860,20 +1816,20 @@ ] } }, - "name": "query18" + "name": "query12" }, { "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": "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": "querytext19" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | 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", @@ -1922,20 +1878,42 @@ ] } }, - "name": "query19" + "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": "## PaaS" + }, + "name": "tab6title" }, { "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": "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": "querytext20" + "name": "querytext22" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/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", @@ -1984,20 +1962,42 @@ ] } }, - "name": "query20" + "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": "## Virtual WAN" + }, + "name": "tab7title" }, { "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": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext21" + "name": "querytext27" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,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/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", @@ -2046,7 +2046,7 @@ ] } }, - "name": "query21" + "name": "query27" } ] }, diff --git a/workbooks/alz_checklist.en_network_workbook_template.json b/workbooks/alz_checklist.en_network_workbook_template.json index 758119953..035b8294d 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\": \"f4366ea4-1a4b-43a5-baa0-36b29f527fb2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab0\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"9495360a-f276-4563-9332-a3a494a0760c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"7567a969-c0a6-4f0e-a548-37aac3df103d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab2\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"592694b9-dc47-4dd2-9333-319f4bbdb598\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f872a398-c4e5-4ae8-938c-f5df3803ffbb\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab4\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d6bc0fc6-40be-4453-8ae9-9eb50a37fd71\",\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\": \"c798787f-d2bf-4aa4-a605-3f3635365fbc\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"20b98487-4573-478c-ae9d-a240da89472d\",\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\": \"## Segmentation\"\n },\n \"name\": \"tab1title\"\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\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext22\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query22\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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\": \"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\": \"## Virtual WAN\"\n },\n \"name\": \"tab6title\"\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\": \"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 over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"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\": \"aeff028d-5064-4bdc-88df-a31017f5f59b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"120d549e-8074-46fb-bbf6-ab0c94891def\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab1\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"87541aba-2c69-4b3c-b3f2-4243137d8eec\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab2\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"67224ece-6b6d-494f-a271-f4d7b87d607b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"55118791-ed80-4890-83cb-2f73c693a113\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6a5edaf8-c526-4b73-b1ae-c4f28810da11\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e924644f-0b80-44d7-b6be-23d1e9026ed8\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab6\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"874e739d-01ae-4feb-a1b5-da7099a215b5\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 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\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\\\.|172\\\\.(1[6-9]|2[0-9]|3[01])\\\\.|192\\\\.168\\\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext15\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query15\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext16\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet over protocols not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext17\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information.\"\n },\n \"name\": \"querytext19\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query19\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information.\"\n },\n \"name\": \"querytext20\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query20\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information.\"\n },\n \"name\": \"querytext21\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query21\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"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\": \"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\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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\": \"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\": \"## Virtual WAN\"\n },\n \"name\": \"tab7title\"\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\": \"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')]"