From 5392320f338980e50bcd0770cd39557e23d61b24 Mon Sep 17 00:00:00 2001 From: erjosito Date: Thu, 29 Jun 2023 14:31:39 +0000 Subject: [PATCH] [create-pull-request] automated change --- checklists/alz_checklist.en.json | 22 +- checklists/alz_checklist.es.json | 30 +- checklists/alz_checklist.ja.json | 30 +- checklists/alz_checklist.ko.json | 30 +- checklists/alz_checklist.pt.json | 30 +- spreadsheet/macrofree/alz_checklist.en.xlsx | Bin 42956 -> 42949 bytes spreadsheet/macrofree/alz_checklist.es.xlsx | Bin 44910 -> 44898 bytes spreadsheet/macrofree/alz_checklist.ja.xlsx | Bin 49310 -> 49295 bytes spreadsheet/macrofree/alz_checklist.ko.xlsx | Bin 47842 -> 47855 bytes spreadsheet/macrofree/alz_checklist.pt.xlsx | Bin 44973 -> 44971 bytes .../alz_checklist.en_counters_workbook.json | 258 ++-- ...ecklist.en_counters_workbook_template.json | 2 +- .../alz_checklist.en_network_counters.json | 522 ++++--- ...hecklist.en_network_counters_template.json | 2 +- .../alz_checklist.en_network_tabcounters.json | 1340 +++++++++-------- ...klist.en_network_tabcounters_template.json | 2 +- .../alz_checklist.en_network_workbook.json | 478 +++--- ...hecklist.en_network_workbook_template.json | 2 +- workbooks/alz_checklist.en_workbook.json | 168 ++- .../alz_checklist.en_workbook_template.json | 2 +- 20 files changed, 1676 insertions(+), 1242 deletions(-) diff --git a/checklists/alz_checklist.en.json b/checklists/alz_checklist.en.json index 66d38cbf5..7683d465e 100644 --- a/checklists/alz_checklist.en.json +++ b/checklists/alz_checklist.en.json @@ -1,14 +1,5 @@ { "items": [ - { - "category": "Network Topology and Connectivity", - "subcategory": "App delivery", - "text": "If you use customer-managed TLS certificates with Azure Front Door, use the 'Latest' certificate version. Reduce the risk of outages caused by manual certificate renewal.", - "waf": "Operations", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "severity": "Medium", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates" - }, { "category": "Backup and Disaster Recovery", "subcategory": "Data Protection", @@ -549,6 +540,15 @@ "severity": "Medium", "link": "https://learn.microsoft.com/azure/automation/how-to/region-mappings" }, + { + "category": "Network Topology and Connectivity", + "subcategory": "App delivery", + "text": "If you use customer-managed TLS certificates with Azure Front Door, use the 'Latest' certificate version. Reduce the risk of outages caused by manual certificate renewal.", + "waf": "Operations", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "severity": "Medium", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates" + }, { "category": "Network Topology and Connectivity", "subcategory": "App delivery", @@ -1968,6 +1968,6 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "May 24, 2023" + "timestamp": "June 29, 2023" } -} +} \ No newline at end of file diff --git a/checklists/alz_checklist.es.json b/checklists/alz_checklist.es.json index 8ce6a8b43..ae30d65cc 100644 --- a/checklists/alz_checklist.es.json +++ b/checklists/alz_checklist.es.json @@ -23,15 +23,6 @@ } ], "items": [ - { - "category": "Entrega de aplicaciones", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", - "severity": "Medio", - "subcategory": "Entrega de aplicaciones", - "text": "Si usa certificados TLS administrados por el cliente con Azure Front Door, use la versión de certificado \"más reciente\". Reduzca el riesgo de interrupciones causadas por la renovación manual de certificados.", - "waf": "Operaciones" - }, { "category": "Copia de seguridad y recuperación ante desastres", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", @@ -572,6 +563,15 @@ "text": "Considerar las regiones admitidas para el área de trabajo de Log Analytics vinculada y las cuentas de automatización", "waf": "Operaciones" }, + { + "category": "Topología y conectividad de red", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "severity": "Medio", + "subcategory": "Entrega de aplicaciones", + "text": "Si usa certificados TLS administrados por el cliente con Azure Front Door, use la versión de certificado \"más reciente\". Reduzca el riesgo de interrupciones causadas por la renovación manual de certificados.", + "waf": "Operaciones" + }, { "category": "Topología y conectividad de red", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", @@ -593,6 +593,16 @@ "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Seguridad" }, + { + "category": "Topología y conectividad de red", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "severity": "Medio", + "subcategory": "Entrega de aplicaciones", + "text": "Asegúrese de que está usando la SKU estándar para los equilibradores de carga de Azure", + "waf": "Seguridad" + }, { "category": "Topología y conectividad de red", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", @@ -1908,7 +1918,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "May 24, 2023" + "timestamp": "June 29, 2023" }, "severities": [ { diff --git a/checklists/alz_checklist.ja.json b/checklists/alz_checklist.ja.json index 136d6e4c0..a5d3e34ad 100644 --- a/checklists/alz_checklist.ja.json +++ b/checklists/alz_checklist.ja.json @@ -23,15 +23,6 @@ } ], "items": [ - { - "category": "アプリ配信", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", - "severity": "中程度", - "subcategory": "アプリ配信", - "text": "Azure Front Door でカスタマー マネージド TLS 証明書を使用する場合は、\"最新\" の証明書バージョンを使用します。証明書の手動更新による停止のリスクを軽減します。", - "waf": "オペレーションズ" - }, { "category": "バックアップと災害復旧", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", @@ -572,6 +563,15 @@ "text": "リンクされた Log Analytics ワークスペースと自動化アカウントでサポートされているリージョンを検討する", "waf": "オペレーションズ" }, + { + "category": "ネットワーク トポロジと接続性", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "severity": "中程度", + "subcategory": "アプリ配信", + "text": "Azure Front Door でカスタマー マネージド TLS 証明書を使用する場合は、\"最新\" の証明書バージョンを使用します。証明書の手動更新による停止のリスクを軽減します。", + "waf": "オペレーションズ" + }, { "category": "ネットワーク トポロジと接続性", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", @@ -593,6 +593,16 @@ "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "安全" }, + { + "category": "ネットワーク トポロジと接続性", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "severity": "中程度", + "subcategory": "アプリ配信", + "text": "Azure ロード バランサーに標準 SKU を使用していることを確認する", + "waf": "安全" + }, { "category": "ネットワーク トポロジと接続性", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", @@ -1908,7 +1918,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "May 24, 2023" + "timestamp": "June 29, 2023" }, "severities": [ { diff --git a/checklists/alz_checklist.ko.json b/checklists/alz_checklist.ko.json index bba02ae2c..ed2cfd8d9 100644 --- a/checklists/alz_checklist.ko.json +++ b/checklists/alz_checklist.ko.json @@ -23,15 +23,6 @@ } ], "items": [ - { - "category": "앱 제공", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", - "severity": "보통", - "subcategory": "앱 제공", - "text": "Azure Front Door에서 고객 관리형 TLS 인증서를 사용하는 경우 '최신' 인증서 버전을 사용합니다. 수동 인증서 갱신으로 인한 중단 위험을 줄입니다.", - "waf": "작업" - }, { "category": "백업 및 재해 복구", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", @@ -572,6 +563,15 @@ "text": "연결된 Log Analytics 작업 영역 및 자동화 계정에 대해 지원되는 지역 고려", "waf": "작업" }, + { + "category": "네트워크 토폴로지 및 연결", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "severity": "보통", + "subcategory": "앱 제공", + "text": "Azure Front Door에서 고객 관리형 TLS 인증서를 사용하는 경우 '최신' 인증서 버전을 사용합니다. 수동 인증서 갱신으로 인한 중단 위험을 줄입니다.", + "waf": "작업" + }, { "category": "네트워크 토폴로지 및 연결", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", @@ -593,6 +593,16 @@ "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "안전" }, + { + "category": "네트워크 토폴로지 및 연결", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "severity": "보통", + "subcategory": "앱 제공", + "text": "Azure Load Balancer에 표준 SKU를 사용하고 있는지 확인합니다.", + "waf": "안전" + }, { "category": "네트워크 토폴로지 및 연결", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", @@ -1908,7 +1918,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "May 24, 2023" + "timestamp": "June 29, 2023" }, "severities": [ { diff --git a/checklists/alz_checklist.pt.json b/checklists/alz_checklist.pt.json index fdecbfe71..c93abe73f 100644 --- a/checklists/alz_checklist.pt.json +++ b/checklists/alz_checklist.pt.json @@ -23,15 +23,6 @@ } ], "items": [ - { - "category": "Entrega de aplicativos", - "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", - "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", - "severity": "Média", - "subcategory": "Entrega de aplicativos", - "text": "Se você usar certificados TLS gerenciados pelo cliente com o Azure Front Door, use a versão de certificado 'Mais recente'. Reduza o risco de paralisações causadas pela renovação manual de certificados.", - "waf": "Operações" - }, { "category": "Backup e recuperação de desastres", "guid": "7ea02e1c-7166-45a3-bdf5-098891367fcb", @@ -572,6 +563,15 @@ "text": "Considere as regiões com suporte para contas vinculadas de espaço de trabalho e automação do Log Analytics", "waf": "Operações" }, + { + "category": "Topologia de rede e conectividade", + "guid": "f00a69de-7076-4734-a734-6e4552cad9e1", + "link": "https://learn.microsoft.com/azure/frontdoor/best-practices#use-latest-version-for-customer-managed-certificates", + "severity": "Média", + "subcategory": "Entrega de aplicativos", + "text": "Se você usar certificados TLS gerenciados pelo cliente com o Azure Front Door, use a versão de certificado 'Mais recente'. Reduza o risco de paralisações causadas pela renovação manual de certificados.", + "waf": "Operações" + }, { "category": "Topologia de rede e conectividade", "guid": "6138a720-0f1c-4e16-bd30-1d6e872e52e3", @@ -593,6 +593,16 @@ "training": "https://learn.microsoft.com/learn/paths/secure-application-delivery/", "waf": "Segurança" }, + { + "category": "Topologia de rede e conectividade", + "graph": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')", + "guid": "4e35fbf5-0ae2-48b2-97ce-753353edbd1a", + "link": "https://learn.microsoft.com/azure/load-balancer/load-balancer-overview", + "severity": "Média", + "subcategory": "Entrega de aplicativos", + "text": "Verifique se você está usando a SKU padrão para seus Balanceadores de Carga do Azure", + "waf": "Segurança" + }, { "category": "Topologia de rede e conectividade", "graph": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant", @@ -1908,7 +1918,7 @@ "metadata": { "name": "Azure Landing Zone Review", "state": "GA", - "timestamp": "May 24, 2023" + "timestamp": "June 29, 2023" }, "severities": [ { diff --git a/spreadsheet/macrofree/alz_checklist.en.xlsx b/spreadsheet/macrofree/alz_checklist.en.xlsx index 90bc95c99823686f5b9b6c05294d87d3060727d2..5a341d5eadb6326f4a22d55f7be26ef0a94d5cf6 100644 GIT binary patch delta 38620 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 Mq^k>RQ@4`;0{rh(0{{R3 delta 38603 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

3F0^|x4xItnlXm diff --git a/spreadsheet/macrofree/alz_checklist.es.xlsx b/spreadsheet/macrofree/alz_checklist.es.xlsx index c2a63c1c93b92886fef8edc617c279eea371b70c..0d8c8c37c711199398aff80672bdaa26f1075457 100644 GIT binary patch delta 40179 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%0Dakt0a-Rk$jJW0YV{R(u{_%B}*1_gZ=?i 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 delta 40228 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 XMGCA^V)w;)E@IX1Z(07n01EjJUkqgx diff --git a/spreadsheet/macrofree/alz_checklist.ja.xlsx b/spreadsheet/macrofree/alz_checklist.ja.xlsx index e5ee15535efdbf791e766f14bdfb6b71142160cb..aca275aecc1f66f356a86034600b235ac3131417 100644 GIT binary patch delta 44407 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 delta 44425 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�-YMI2-RR6yJuE}ux?uzGSs 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 delta 40029 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

4>I=)mJ&e;;Pw7^B{jc=gtm^hNf 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 T{>lgqRty5!>lVpm3J(4UB`og2 diff --git a/workbooks/alz_checklist.en_counters_workbook.json b/workbooks/alz_checklist.en_counters_workbook.json index 30ba34d83..0f19b8139 100644 --- a/workbooks/alz_checklist.en_counters_workbook.json +++ b/workbooks/alz_checklist.en_counters_workbook.json @@ -208,7 +208,7 @@ "version": "KqlParameterItem/1.0", "name": "Query5Stats", "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/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}" ], @@ -236,7 +236,7 @@ "version": "KqlParameterItem/1.0", "name": "Query6Stats", "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/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}" ], @@ -264,7 +264,7 @@ "version": "KqlParameterItem/1.0", "name": "Query7Stats", "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/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}" ], @@ -292,7 +292,7 @@ "version": "KqlParameterItem/1.0", "name": "Query8Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/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}" ], @@ -320,7 +320,7 @@ "version": "KqlParameterItem/1.0", "name": "Query9Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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}" ], @@ -348,7 +348,7 @@ "version": "KqlParameterItem/1.0", "name": "Query10Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "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}" ], @@ -376,7 +376,7 @@ "version": "KqlParameterItem/1.0", "name": "Query11Stats", "type": 1, - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -404,7 +404,7 @@ "version": "KqlParameterItem/1.0", "name": "Query12Stats", "type": 1, - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -432,7 +432,7 @@ "version": "KqlParameterItem/1.0", "name": "Query13Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -460,7 +460,7 @@ "version": "KqlParameterItem/1.0", "name": "Query14Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -488,7 +488,7 @@ "version": "KqlParameterItem/1.0", "name": "Query15Stats", "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/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -516,7 +516,7 @@ "version": "KqlParameterItem/1.0", "name": "Query16Stats", "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' | 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}" ], @@ -544,7 +544,7 @@ "version": "KqlParameterItem/1.0", "name": "Query17Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "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}" ], @@ -572,7 +572,7 @@ "version": "KqlParameterItem/1.0", "name": "Query18Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -600,7 +600,7 @@ "version": "KqlParameterItem/1.0", "name": "Query19Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -628,7 +628,7 @@ "version": "KqlParameterItem/1.0", "name": "Query20Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -656,7 +656,7 @@ "version": "KqlParameterItem/1.0", "name": "Query21Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -684,7 +684,7 @@ "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,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -712,7 +712,7 @@ "version": "KqlParameterItem/1.0", "name": "Query23Stats", "type": 1, - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -740,7 +740,7 @@ "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 == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -768,7 +768,7 @@ "version": "KqlParameterItem/1.0", "name": "Query25Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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}" ], @@ -796,7 +796,7 @@ "version": "KqlParameterItem/1.0", "name": "Query26Stats", "type": 1, - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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}" ], @@ -824,7 +824,7 @@ "version": "KqlParameterItem/1.0", "name": "Query27Stats", "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/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}" ], @@ -852,7 +852,7 @@ "version": "KqlParameterItem/1.0", "name": "Query28Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,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}" ], @@ -880,7 +880,7 @@ "version": "KqlParameterItem/1.0", "name": "Query29Stats", "type": 1, - "query": "ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "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}" ], @@ -903,6 +903,34 @@ }, "queryType": 8 }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query30Stats", + "type": 1, + "query": "ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query30FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query30Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", @@ -917,7 +945,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}" + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}" } } ] @@ -936,7 +964,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}" + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}" } } ] @@ -974,7 +1002,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query29Stats:$.Success}" + "resultVal": "{Query30Stats:$.Success}" } } ] @@ -993,7 +1021,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query29Stats:$.Total}" + "resultVal": "{Query30Stats:$.Total}" } } ] @@ -1088,7 +1116,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" + "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query30Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" } } ] @@ -1107,7 +1135,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" + "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query30Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" } } ] @@ -1181,7 +1209,7 @@ "style": "tabs", "links": [ { - "id": "c85f7cab-f489-4182-a1d6-3adc399bfa37", + "id": "763c2e8a-43e5-4c7c-be74-8035f966df75", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})", @@ -1190,7 +1218,7 @@ "style": "primary" }, { - "id": "927921b6-8bdb-4b30-b9c7-501cc2b2888c", + "id": "0ac23195-1d8c-43a1-9362-207ec17dfc49", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Security, Governance and Compliance ({Tab1Success:value}/{Tab1Total:value})", @@ -1199,7 +1227,7 @@ "style": "primary" }, { - "id": "b6e549d4-f666-429f-8682-f4a73b1dfa9e", + "id": "824cff63-0a7d-42b1-b4c1-f0ef9113aa09", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Management Group and Subscriptions ({Tab2Success:value}/{Tab2Total:value})", @@ -1289,7 +1317,7 @@ { "type": 1, "content": { - "json": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." + "json": "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": "querytext5" }, @@ -1297,7 +1325,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/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", @@ -1351,7 +1379,7 @@ { "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": "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": "querytext6" }, @@ -1359,7 +1387,7 @@ "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/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", @@ -1413,7 +1441,7 @@ { "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": "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": "querytext7" }, @@ -1421,7 +1449,7 @@ "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/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", @@ -1475,7 +1503,7 @@ { "type": 1, "content": { - "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." + "json": "Use Azure 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": "querytext8" }, @@ -1483,7 +1511,7 @@ "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/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", @@ -1537,7 +1565,7 @@ { "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": "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": "querytext9" }, @@ -1545,7 +1573,7 @@ "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,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", @@ -1599,7 +1627,7 @@ { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use 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": "querytext10" }, @@ -1607,7 +1635,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -1661,7 +1689,7 @@ { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Ensure that 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": "querytext11" }, @@ -1669,7 +1697,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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", @@ -1723,7 +1751,7 @@ { "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": "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": "querytext12" }, @@ -1731,7 +1759,7 @@ "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/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", @@ -1785,7 +1813,7 @@ { "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": "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": "querytext13" }, @@ -1793,7 +1821,7 @@ "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/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", @@ -1847,7 +1875,7 @@ { "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": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, "name": "querytext14" }, @@ -1855,7 +1883,7 @@ "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/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", @@ -1909,7 +1937,7 @@ { "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 VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." }, "name": "querytext15" }, @@ -1917,7 +1945,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | 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", @@ -1971,7 +1999,7 @@ { "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 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": "querytext16" }, @@ -1979,7 +2007,7 @@ "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' | 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", @@ -2033,7 +2061,7 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." + "json": "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": "querytext17" }, @@ -2041,7 +2069,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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", @@ -2095,7 +2123,7 @@ { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." }, "name": "querytext18" }, @@ -2103,7 +2131,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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", @@ -2157,7 +2185,7 @@ { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, "name": "querytext19" }, @@ -2165,7 +2193,7 @@ "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/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", @@ -2219,7 +2247,7 @@ { "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 Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, "name": "querytext20" }, @@ -2227,7 +2255,7 @@ "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/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", @@ -2281,7 +2309,7 @@ { "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": "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": "querytext21" }, @@ -2289,7 +2317,7 @@ "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/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", @@ -2343,7 +2371,7 @@ { "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": "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": "querytext22" }, @@ -2351,7 +2379,7 @@ "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/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", @@ -2405,7 +2433,7 @@ { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, "name": "querytext23" }, @@ -2413,7 +2441,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2467,7 +2495,7 @@ { "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": "querytext24" }, @@ -2475,7 +2503,7 @@ "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2529,7 +2557,7 @@ { "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 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": "querytext25" }, @@ -2537,7 +2565,7 @@ "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' | 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", @@ -2591,7 +2619,7 @@ { "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 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": "querytext26" }, @@ -2599,7 +2627,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -2653,7 +2681,7 @@ { "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": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." }, "name": "querytext27" }, @@ -2661,7 +2689,7 @@ "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/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", @@ -2715,7 +2743,7 @@ { "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": "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": "querytext28" }, @@ -2723,7 +2751,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -2773,6 +2801,68 @@ } }, "name": "query28" + }, + { + "type": 1, + "content": { + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + }, + "name": "querytext29" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 0, + "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": "query29" } ] }, @@ -2801,7 +2891,7 @@ "content": { "json": "Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information." }, - "name": "querytext29" + "name": "querytext30" }, { "type": 3, @@ -2856,7 +2946,7 @@ ] } }, - "name": "query29" + "name": "query30" } ] }, diff --git a/workbooks/alz_checklist.en_counters_workbook_template.json b/workbooks/alz_checklist.en_counters_workbook_template.json index 95abce0fb..40177071a 100644 --- a/workbooks/alz_checklist.en_counters_workbook_template.json +++ b/workbooks/alz_checklist.en_counters_workbook_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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 | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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 | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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' | 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\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | 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\": \"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/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\": \"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/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\": \"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/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\": \"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' 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\": \"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/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\": \"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 | 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\": \"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' | 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\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,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\": \"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.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\": \"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.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\": \"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.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\": \"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/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\": \"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,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\": \"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,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\": \"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 == '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\": \"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/virtualnetworks' | 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\": \"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/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\": \"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/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\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query28Stats\",\n \"type\": 1,\n \"query\": \"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\": \"Query28FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query28Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29Stats\",\n \"type\": 1,\n \"query\": \"ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query29Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.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\": \"{Query29Stats:$.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\": \"{Query29Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"c85f7cab-f489-4182-a1d6-3adc399bfa37\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"927921b6-8bdb-4b30-b9c7-501cc2b2888c\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security, Governance and Compliance ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security, Governance and Compliance\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b6e549d4-f666-429f-8682-f4a73b1dfa9e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Management Group and Subscriptions ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Management Group and Subscriptions\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"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' 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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"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 | 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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext17\"\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\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"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 == '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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"querytext27\"\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\": \"query27\"\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\": \"querytext28\"\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\": \"query28\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Security, Governance and Compliance\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext29\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query29\"\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\": \"## Management Group and Subscriptions\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than three to four levels, ideally. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"value::all\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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 | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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 | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"Query8FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query8Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query9Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | 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\": \"Query9FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query9Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query10Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | 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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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' | 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\": \"Query16FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query16Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query17Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | 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\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"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.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\": \"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.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\": \"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/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\": \"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/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\": \"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,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\": \"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,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\": \"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/virtualnetworks' | 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\": \"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,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\": \"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/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\": \"Query27FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query27Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query28Stats\",\n \"type\": 1,\n \"query\": \"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\": \"Query28FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query28Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query29Stats\",\n \"type\": 1,\n \"query\": \"resources | 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\": \"Query29FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query29Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query30Stats\",\n \"type\": 1,\n \"query\": \"ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query30FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query30Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.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\": \"{Query30Stats:$.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\": \"{Query30Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab2Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab2Success}/{Tab2Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookTotal\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query25Stats:$.Total}+{Query26Stats:$.Total}+{Query27Stats:$.Total}+{Query28Stats:$.Total}+{Query29Stats:$.Total}+{Query30Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query25Stats:$.Success}+{Query26Stats:$.Success}+{Query27Stats:$.Success}+{Query28Stats:$.Success}+{Query29Stats:$.Success}+{Query30Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookPercent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{WorkbookSuccess}/{WorkbookTotal})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"InvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"50\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"WorkbookPercent\\\\\\\": \\\\\\\"{WorkbookPercent}\\\\\\\", \\\\\\\"SubTitle\\\\\\\": \\\\\\\"Percent of successful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 4,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"WorkbookPercent\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"SubTitle\",\n \"formatter\": 1\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"ProgressTile\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"763c2e8a-43e5-4c7c-be74-8035f966df75\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"0ac23195-1d8c-43a1-9362-207ec17dfc49\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security, Governance and Compliance ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security, Governance and Compliance\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"824cff63-0a7d-42b1-b4c1-f0ef9113aa09\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Management Group and Subscriptions ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Management Group and Subscriptions\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"querytext27\"\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\": \"query27\"\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\": \"querytext28\"\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\": \"query28\"\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\": \"querytext29\"\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\": \"query29\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Security, Governance and Compliance\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext30\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query30\"\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\": \"## Management Group and Subscriptions\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than three to four levels, ideally. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/alz_checklist.en_network_counters.json b/workbooks/alz_checklist.en_network_counters.json index 19a823868..607c1437f 100644 --- a/workbooks/alz_checklist.en_network_counters.json +++ b/workbooks/alz_checklist.en_network_counters.json @@ -96,7 +96,7 @@ "version": "KqlParameterItem/1.0", "name": "Query1Stats", "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/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}" ], @@ -124,7 +124,7 @@ "version": "KqlParameterItem/1.0", "name": "Query2Stats", "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/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}" ], @@ -152,7 +152,7 @@ "version": "KqlParameterItem/1.0", "name": "Query3Stats", "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/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}" ], @@ -180,7 +180,7 @@ "version": "KqlParameterItem/1.0", "name": "Query4Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/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}" ], @@ -208,7 +208,7 @@ "version": "KqlParameterItem/1.0", "name": "Query5Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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}" ], @@ -236,7 +236,7 @@ "version": "KqlParameterItem/1.0", "name": "Query6Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "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}" ], @@ -264,7 +264,7 @@ "version": "KqlParameterItem/1.0", "name": "Query7Stats", "type": 1, - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -292,7 +292,7 @@ "version": "KqlParameterItem/1.0", "name": "Query8Stats", "type": 1, - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -320,7 +320,7 @@ "version": "KqlParameterItem/1.0", "name": "Query9Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -348,7 +348,7 @@ "version": "KqlParameterItem/1.0", "name": "Query10Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -376,7 +376,7 @@ "version": "KqlParameterItem/1.0", "name": "Query11Stats", "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/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -404,7 +404,7 @@ "version": "KqlParameterItem/1.0", "name": "Query12Stats", "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' | 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}" ], @@ -432,7 +432,7 @@ "version": "KqlParameterItem/1.0", "name": "Query13Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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())", + "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}" ], @@ -460,7 +460,7 @@ "version": "KqlParameterItem/1.0", "name": "Query14Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -488,7 +488,7 @@ "version": "KqlParameterItem/1.0", "name": "Query15Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -516,7 +516,7 @@ "version": "KqlParameterItem/1.0", "name": "Query16Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -544,7 +544,7 @@ "version": "KqlParameterItem/1.0", "name": "Query17Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -572,7 +572,7 @@ "version": "KqlParameterItem/1.0", "name": "Query18Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -600,7 +600,7 @@ "version": "KqlParameterItem/1.0", "name": "Query19Stats", "type": 1, - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -628,7 +628,7 @@ "version": "KqlParameterItem/1.0", "name": "Query20Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -656,7 +656,7 @@ "version": "KqlParameterItem/1.0", "name": "Query21Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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}" ], @@ -684,7 +684,7 @@ "version": "KqlParameterItem/1.0", "name": "Query22Stats", "type": 1, - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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}" ], @@ -712,7 +712,7 @@ "version": "KqlParameterItem/1.0", "name": "Query23Stats", "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/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}" ], @@ -740,7 +740,7 @@ "version": "KqlParameterItem/1.0", "name": "Query24Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,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}" ], @@ -763,6 +763,34 @@ }, "queryType": 8 }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query25Stats", + "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": "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", @@ -777,7 +805,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}" + "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}" } } ] @@ -796,7 +824,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}" + "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}" } } ] @@ -834,7 +862,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query24Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}" } } ] @@ -853,7 +881,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query24Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}" } } ] @@ -891,7 +919,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}" + "resultVal": "{Query20Stats:$.Success}" } } ] @@ -910,7 +938,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}" + "resultVal": "{Query20Stats:$.Total}" } } ] @@ -948,7 +976,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}" + "resultVal": "{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}" } } ] @@ -967,7 +995,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}" + "resultVal": "{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}" } } ] @@ -1005,7 +1033,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}" } } ] @@ -1024,7 +1052,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}" } } ] @@ -1062,7 +1090,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}" + "resultVal": "{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}" } } ] @@ -1081,7 +1109,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}" + "resultVal": "{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}" } } ] @@ -1119,7 +1147,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -1138,7 +1166,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" } } ] @@ -1176,7 +1204,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Success}" + "resultVal": "{Query25Stats:$.Success}" } } ] @@ -1195,7 +1223,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Total}" + "resultVal": "{Query25Stats:$.Total}" } } ] @@ -1233,7 +1261,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query24Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query19Stats:$.Total}" + "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query25Stats:$.Total}" } } ] @@ -1252,7 +1280,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query24Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query19Stats:$.Success}" + "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query25Stats:$.Success}" } } ] @@ -1326,75 +1354,75 @@ "style": "tabs", "links": [ { - "id": "44f1d219-fc87-4630-a061-d0695d803d28", + "id": "90732ba0-3ff6-4f50-aff4-32a14328d154", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke ({Tab0Success:value}/{Tab0Total:value})", + "linkLabel": "IP plan ({Tab0Success:value}/{Tab0Total:value})", "subTarget": "tab0", - "preText": "Hub and spoke", + "preText": "IP plan", "style": "primary" }, { - "id": "2f17e335-526a-42fd-aaaf-0db3038d12c2", + "id": "f6a03586-e881-4206-b24c-43a242aa6865", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN ({Tab1Success:value}/{Tab1Total:value})", + "linkLabel": "Internet ({Tab1Success:value}/{Tab1Total:value})", "subTarget": "tab1", - "preText": "Virtual WAN", + "preText": "Internet", "style": "primary" }, { - "id": "e8e19466-c6c2-43a7-bfaa-f35986b953a7", + "id": "5e712083-6b8c-4dab-8f68-e458a1d21ef1", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet ({Tab2Success:value}/{Tab2Total:value})", + "linkLabel": "PaaS ({Tab2Success:value}/{Tab2Total:value})", "subTarget": "tab2", - "preText": "Internet", + "preText": "PaaS", "style": "primary" }, { - "id": "3d62bbd4-70d4-4d62-a0e8-404111ac4349", + "id": "d99d82bd-0359-42eb-b29f-110ba4964304", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan ({Tab3Success:value}/{Tab3Total:value})", + "linkLabel": "Segmentation ({Tab3Success:value}/{Tab3Total:value})", "subTarget": "tab3", - "preText": "IP plan", + "preText": "Segmentation", "style": "primary" }, { - "id": "7aa7f3e6-665d-4c70-83da-feb5c3ec84b1", + "id": "7a8b3f4f-07ed-4d1c-a80d-da7ee7d50eb9", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery ({Tab4Success:value}/{Tab4Total:value})", + "linkLabel": "Hub and spoke ({Tab4Success:value}/{Tab4Total:value})", "subTarget": "tab4", - "preText": "App delivery", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "1197cdaf-76de-486f-a719-cfc0242cfab0", + "id": "9b5c904f-e526-45a0-8803-7a3d62fdb5af", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation ({Tab5Success:value}/{Tab5Total:value})", + "linkLabel": "Hybrid ({Tab5Success:value}/{Tab5Total:value})", "subTarget": "tab5", - "preText": "Segmentation", + "preText": "Hybrid", "style": "primary" }, { - "id": "e8edf0a0-8078-4ce3-90f2-99405aafaffe", + "id": "42ad440d-932d-41c9-95c8-69ffdcdefc4d", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid ({Tab6Success:value}/{Tab6Total:value})", + "linkLabel": "App delivery ({Tab6Success:value}/{Tab6Total:value})", "subTarget": "tab6", - "preText": "Hybrid", + "preText": "App delivery", "style": "primary" }, { - "id": "b6a7f9de-4352-451f-b6a5-fd4988579d90", + "id": "ef064f1a-3206-48bc-b4ea-dadab65b02be", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS ({Tab7Success:value}/{Tab7Total:value})", + "linkLabel": "Virtual WAN ({Tab7Success:value}/{Tab7Total:value})", "subTarget": "tab7", - "preText": "PaaS", + "preText": "Virtual WAN", "style": "primary" } ] @@ -1410,22 +1438,22 @@ { "type": 1, "content": { - "json": "## Hub and spoke" + "json": "## IP plan" }, "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": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext4" + "name": "querytext12" }, { "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", @@ -1474,20 +1502,20 @@ ] } }, - "name": "query4" + "name": "query12" }, { "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": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext5" + "name": "querytext13" }, { "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' | 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", @@ -1536,7 +1564,7 @@ ] } }, - "name": "query5" + "name": "query13" } ] }, @@ -1556,22 +1584,22 @@ { "type": 1, "content": { - "json": "## Virtual WAN" + "json": "## Internet" }, "name": "tab1title" }, { "type": 1, "content": { - "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext24" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1620,42 +1648,20 @@ ] } }, - "name": "query24" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab1" - }, - "name": "tab1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Internet" - }, - "name": "tab2title" + "name": "query14" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext13" + "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 == '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/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1704,20 +1710,20 @@ ] } }, - "name": "query13" + "name": "query15" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext14" + "name": "querytext16" }, { "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/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1766,20 +1772,20 @@ ] } }, - "name": "query14" + "name": "query16" }, { "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": "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": "querytext15" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1828,20 +1834,20 @@ ] } }, - "name": "query15" + "name": "query17" }, { "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": "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": "querytext16" + "name": "querytext18" }, { "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/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1890,20 +1896,20 @@ ] } }, - "name": "query16" + "name": "query18" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, - "name": "querytext17" + "name": "querytext19" }, { "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,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1952,20 +1958,42 @@ ] } }, - "name": "query17" + "name": "query19" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab1" + }, + "name": "tab1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab2title" }, { "type": 1, "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." }, - "name": "querytext18" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -2014,7 +2042,7 @@ ] } }, - "name": "query18" + "name": "query20" } ] }, @@ -2034,22 +2062,22 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Segmentation" }, "name": "tab3title" }, { "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": "querytext11" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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", @@ -2098,20 +2126,20 @@ ] } }, - "name": "query11" + "name": "query21" }, { "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": "querytext12" + "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,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", @@ -2160,42 +2188,20 @@ ] } }, - "name": "query12" - } - ] - }, - "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": "query22" }, { "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": "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": "querytext0" + "name": "querytext23" }, { "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/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", @@ -2244,20 +2250,20 @@ ] } }, - "name": "query0" + "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": "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": "querytext1" + "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,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", @@ -2306,20 +2312,42 @@ ] } }, - "name": "query1" + "name": "query24" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab3" + }, + "name": "tab3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Hub and spoke" + }, + "name": "tab4title" }, { "type": 1, "content": { - "json": "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": "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": "querytext2" + "name": "querytext5" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | 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", @@ -2368,20 +2396,20 @@ ] } }, - "name": "query2" + "name": "query5" }, { "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": "querytext3" + "name": "querytext6" }, { "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", @@ -2430,7 +2458,7 @@ ] } }, - "name": "query3" + "name": "query6" } ] }, @@ -2450,22 +2478,22 @@ { "type": 1, "content": { - "json": "## Segmentation" + "json": "## Hybrid" }, "name": "tab5title" }, { "type": 1, "content": { - "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." + "json": "Ensure that you're using 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": "querytext20" + "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/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", @@ -2514,20 +2542,20 @@ ] } }, - "name": "query20" + "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": "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": "querytext21" + "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/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", @@ -2576,20 +2604,20 @@ ] } }, - "name": "query21" + "name": "query8" }, { "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": "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": "querytext22" + "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/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", @@ -2638,20 +2666,20 @@ ] } }, - "name": "query22" + "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": "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": "querytext23" + "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/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", @@ -2700,7 +2728,69 @@ ] } }, - "name": "query23" + "name": "query10" + }, + { + "type": 1, + "content": { + "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." + }, + "name": "querytext11" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query11" } ] }, @@ -2720,22 +2810,22 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## App delivery" }, "name": "tab6title" }, { "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 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": "querytext6" + "name": "querytext0" }, { "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/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", @@ -2784,20 +2874,20 @@ ] } }, - "name": "query6" + "name": "query0" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Ensure 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": "querytext7" + "name": "querytext1" }, { "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/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", @@ -2846,20 +2936,20 @@ ] } }, - "name": "query7" + "name": "query1" }, { "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": "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": "querytext8" + "name": "querytext2" }, { "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/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", @@ -2908,20 +2998,20 @@ ] } }, - "name": "query8" + "name": "query2" }, { "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": "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": "querytext9" + "name": "querytext3" }, { "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/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", @@ -2970,20 +3060,20 @@ ] } }, - "name": "query9" + "name": "query3" }, { "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 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": "querytext10" + "name": "querytext4" }, { "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/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", @@ -3032,7 +3122,7 @@ ] } }, - "name": "query10" + "name": "query4" } ] }, @@ -3052,22 +3142,22 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## Virtual WAN" }, "name": "tab7title" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "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": "querytext19" + "name": "querytext25" }, { "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", @@ -3116,7 +3206,7 @@ ] } }, - "name": "query19" + "name": "query25" } ] }, diff --git a/workbooks/alz_checklist.en_network_counters_template.json b/workbooks/alz_checklist.en_network_counters_template.json index db170bf37..ac8cb8d57 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/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\": \"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/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\": \"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/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\": \"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/virtualnetworks' | 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\": \"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' | 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\": \"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/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\": \"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/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\": \"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/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\": \"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 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\": \"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/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\": \"Query10FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query10Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query11Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/virtualnetworks' | 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\": \"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/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\": \"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/virtualnetworks' | 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\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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/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\": \"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.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\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,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\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type =~ 'microsoft.network/virtualnetworks' | project id,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\": \"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/virtualnetworks' | 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\": \"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,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\": \"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/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\": \"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,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\": \"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/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\": \"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\": \"Tab0Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}\"\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\": \"{Query24Stats:$.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\": \"{Query24Stats:$.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\": \"{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.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\": \"{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.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\": \"{Query11Stats:$.Success}+{Query12Stats:$.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\": \"{Query11Stats:$.Total}+{Query12Stats:$.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}\"\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}\"\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\": \"{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab6Success}/{Tab6Total})\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query19Stats:$.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\": \"{Query19Stats:$.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\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}+{Query24Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query11Stats:$.Total}+{Query12Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query19Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"WorkbookSuccess\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}+{Query24Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query11Stats:$.Success}+{Query12Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query19Stats:$.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\": \"44f1d219-fc87-4630-a061-d0695d803d28\",\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\": \"2f17e335-526a-42fd-aaaf-0db3038d12c2\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e8e19466-c6c2-43a7-bfaa-f35986b953a7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3d62bbd4-70d4-4d62-a0e8-404111ac4349\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"7aa7f3e6-665d-4c70-83da-feb5c3ec84b1\",\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\": \"1197cdaf-76de-486f-a719-cfc0242cfab0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e8edf0a0-8078-4ce3-90f2-99405aafaffe\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b6a7f9de-4352-451f-b6a5-fd4988579d90\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab7Success:value}/{Tab7Total:value})\",\n \"subTarget\": \"tab7\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext24\"\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\": \"query24\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | 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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"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\": \"querytext1\"\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\": \"query1\"\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\": \"querytext2\"\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\": \"query2\"\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\": \"querytext3\"\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\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"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 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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab7title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext19\"\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\": \"query19\"\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 | 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\": \"Query6FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query6Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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' | 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\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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/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\": \"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.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\": \"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.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\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,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\": \"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/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\": \"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,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\": \"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,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\": \"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/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\": \"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,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\": \"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/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\": \"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\": \"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\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n },\n {\n \"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}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.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}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.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\": \"{Query20Stats:$.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\": \"{Query20Stats:$.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\": \"{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.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\": \"{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.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\": \"{Query5Stats:$.Success}+{Query6Stats:$.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\": \"{Query5Stats:$.Total}+{Query6Stats:$.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\": \"{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.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\": \"{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.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\": \"{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\": \"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\": \"{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\": \"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\": \"{Query25Stats:$.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\": \"{Query25Stats:$.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\": \"{Query12Stats:$.Total}+{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}+{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}+{Query5Stats:$.Total}+{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}+{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}+{Query25Stats:$.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\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}+{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}+{Query5Stats:$.Success}+{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}+{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}+{Query25Stats:$.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\": \"90732ba0-3ff6-4f50-aff4-32a14328d154\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan ({Tab0Success:value}/{Tab0Total:value})\",\n \"subTarget\": \"tab0\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f6a03586-e881-4206-b24c-43a242aa6865\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet ({Tab1Success:value}/{Tab1Total:value})\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5e712083-6b8c-4dab-8f68-e458a1d21ef1\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS ({Tab2Success:value}/{Tab2Total:value})\",\n \"subTarget\": \"tab2\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"d99d82bd-0359-42eb-b29f-110ba4964304\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation ({Tab3Success:value}/{Tab3Total:value})\",\n \"subTarget\": \"tab3\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"7a8b3f4f-07ed-4d1c-a80d-da7ee7d50eb9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke ({Tab4Success:value}/{Tab4Total:value})\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"9b5c904f-e526-45a0-8803-7a3d62fdb5af\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid ({Tab5Success:value}/{Tab5Total:value})\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"42ad440d-932d-41c9-95c8-69ffdcdefc4d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery ({Tab6Success:value}/{Tab6Total:value})\",\n \"subTarget\": \"tab6\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"ef064f1a-3206-48bc-b4ea-dadab65b02be\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN ({Tab7Success:value}/{Tab7Total:value})\",\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\": \"## 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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext14\"\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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"## Segmentation\"\n },\n \"name\": \"tab3title\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"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\": \"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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"## App delivery\"\n },\n \"name\": \"tab6title\"\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\": \"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\": \"querytext25\"\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\": \"query25\"\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 0e79c926d..5cfcb33b2 100644 --- a/workbooks/alz_checklist.en_network_tabcounters.json +++ b/workbooks/alz_checklist.en_network_tabcounters.json @@ -70,25 +70,25 @@ "style": "tabs", "links": [ { - "id": "4f56be24-9e5b-4de8-837d-7eedbd5070c9", + "id": "ba405107-7b09-4dc9-ae90-e6773d324208", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Internet", "subTarget": "tab0", - "preText": "Hybrid", + "preText": "Internet", "style": "primary" }, { - "id": "81e68b16-41bc-4b82-a85e-e7c8924c2687", + "id": "8711320c-1100-4ca2-8ce5-d7b90a03deb0", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "App delivery", + "linkLabel": "PaaS", "subTarget": "tab1", - "preText": "App delivery", + "preText": "PaaS", "style": "primary" }, { - "id": "accf5249-1c25-4cb1-bbc5-96f8c9615e05", + "id": "670e23fb-092c-489b-af46-1aeaf6574f9f", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Segmentation", @@ -97,25 +97,25 @@ "style": "primary" }, { - "id": "110d6170-cfb2-4c07-be7b-0ecff2dc9cec", + "id": "a447f510-1c5d-4429-9d89-24f0970ee2d7", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "App delivery", "subTarget": "tab3", - "preText": "IP plan", + "preText": "App delivery", "style": "primary" }, { - "id": "79a832b0-b2be-4787-8067-992a9df616cd", + "id": "b91d286d-205b-454b-ae21-c59a7bfe5407", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "IP plan", "subTarget": "tab4", - "preText": "PaaS", + "preText": "IP plan", "style": "primary" }, { - "id": "cb424601-9d10-414a-8157-83fc9d17b8f7", + "id": "67ed632a-cab5-4996-b6ed-637c9d2c93d9", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Virtual WAN", @@ -124,7 +124,7 @@ "style": "primary" }, { - "id": "2b0d998f-4dba-46be-b763-159034e08a2e", + "id": "8cac181f-2a84-488a-a417-4c293dae16a4", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Hub and spoke", @@ -133,12 +133,12 @@ "style": "primary" }, { - "id": "feefdce7-a014-4d19-9086-f3112ae18e14", + "id": "dcb189e5-2323-45af-99c8-0160f369e4a4", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "Hybrid", "subTarget": "tab7", - "preText": "Internet", + "preText": "Hybrid", "style": "primary" } ] @@ -162,9 +162,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6Stats", + "name": "Query14Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -178,9 +178,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query6FullyCompliant", + "name": "Query14FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -190,9 +190,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7Stats", + "name": "Query15Stats", "type": 1, - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -206,9 +206,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query7FullyCompliant", + "name": "Query15FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -218,9 +218,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8Stats", + "name": "Query16Stats", "type": 1, - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -234,9 +234,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query8FullyCompliant", + "name": "Query16FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -246,9 +246,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query9Stats", + "name": "Query17Stats", "type": 1, - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -262,9 +262,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query9FullyCompliant", + "name": "Query17FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query9Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -274,9 +274,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query10Stats", + "name": "Query18Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -290,9 +290,37 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query10FullyCompliant", + "name": "Query18FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query10Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query19Stats", + "type": 1, + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "crossComponentResources": [ + "{Subscription}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query19FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -313,7 +341,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}" + "resultVal": "{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.Success}" } } ] @@ -332,7 +360,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}" + "resultVal": "{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}" } } ] @@ -366,7 +394,7 @@ { "type": 1, "content": { - "json": "## Hybrid" + "json": "## Internet" }, "customWidth": "50", "name": "tab0title" @@ -407,15 +435,15 @@ { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext6" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -464,20 +492,20 @@ ] } }, - "name": "query6" + "name": "query14" }, { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext7" + "name": "querytext15" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -526,20 +554,20 @@ ] } }, - "name": "query7" + "name": "query15" }, { "type": 1, "content": { - "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext8" + "name": "querytext16" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -588,20 +616,20 @@ ] } }, - "name": "query8" + "name": "query16" }, { "type": 1, "content": { - "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext9" + "name": "querytext17" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -650,20 +678,20 @@ ] } }, - "name": "query9" + "name": "query17" }, { "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": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext10" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -712,7 +740,69 @@ ] } }, - "name": "query10" + "name": "query18" + }, + { + "type": 1, + "content": { + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + }, + "name": "querytext19" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query19" } ] }, @@ -740,9 +830,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0Stats", + "name": "Query20Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,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}" ], @@ -756,9 +846,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query0FullyCompliant", + "name": "Query20FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -768,129 +858,45 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query1Stats", - "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": "Query1FullyCompliant", + "name": "Tab1Success", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query1Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 }, - "queryType": 8 + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query20Stats:$.Success}" + } + } + ] }, { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query2Stats", + "name": "Tab1Total", "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" + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "{Query20Stats:$.Total}" + } + } + ] }, { "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/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": "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": "Tab1Success", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab1Total", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}" - } - } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab1Percent", + "name": "Tab1Percent", "type": 1, "isHiddenWhenLocked": true, "timeContext": { @@ -916,7 +922,7 @@ { "type": 1, "content": { - "json": "## App delivery" + "json": "## PaaS" }, "customWidth": "50", "name": "tab1title" @@ -957,201 +963,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": "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": "querytext1" - }, - { - "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" - } - } - }, - { - "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": "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": "querytext2" - }, - { - "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", - "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": "query2" - }, - { - "type": 1, - "content": { - "json": "Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information." + "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." }, - "name": "querytext3" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1200,7 +1020,7 @@ ] } }, - "name": "query3" + "name": "query20" } ] }, @@ -1228,7 +1048,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query20Stats", + "name": "Query21Stats", "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": [ @@ -1244,9 +1064,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query20FullyCompliant", + "name": "Query21FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query20Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1256,7 +1076,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21Stats", + "name": "Query22Stats", "type": 1, "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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": [ @@ -1272,9 +1092,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query21FullyCompliant", + "name": "Query22FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query21Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1284,7 +1104,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22Stats", + "name": "Query23Stats", "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": [ @@ -1300,9 +1120,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query22FullyCompliant", + "name": "Query23FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query22Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1312,7 +1132,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23Stats", + "name": "Query24Stats", "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": [ @@ -1328,9 +1148,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query23FullyCompliant", + "name": "Query24FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query23Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1351,7 +1171,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}" + "resultVal": "{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.Success}" } } ] @@ -1370,7 +1190,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}" + "resultVal": "{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.Total}" } } ] @@ -1447,7 +1267,7 @@ "content": { "json": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext20" + "name": "querytext21" }, { "type": 3, @@ -1502,14 +1322,14 @@ ] } }, - "name": "query20" + "name": "query21" }, { "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": "querytext21" + "name": "querytext22" }, { "type": 3, @@ -1564,14 +1384,14 @@ ] } }, - "name": "query21" + "name": "query22" }, { "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": "querytext22" + "name": "querytext23" }, { "type": 3, @@ -1626,14 +1446,14 @@ ] } }, - "name": "query22" + "name": "query23" }, { "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": "querytext23" + "name": "querytext24" }, { "type": 3, @@ -1688,7 +1508,7 @@ ] } }, - "name": "query23" + "name": "query24" } ] }, @@ -1716,9 +1536,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11Stats", + "name": "Query0Stats", "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/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}" ], @@ -1732,9 +1552,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query11FullyCompliant", + "name": "Query0FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query0Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -1744,9 +1564,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query12Stats", + "name": "Query1Stats", "type": 1, - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type == 'microsoft.network/loadbalancers' | 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}" ], @@ -1760,9 +1580,93 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query12FullyCompliant", + "name": "Query1FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query12Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "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 @@ -1783,7 +1687,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Success}+{Query12Stats:$.Success}" + "resultVal": "{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}" } } ] @@ -1802,90 +1706,276 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query11Stats:$.Total}+{Query12Stats:$.Total}" + "resultVal": "{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}" + } + } + ] + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Tab3Percent", + "type": 1, + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "criteriaData": [ + { + "criteriaContext": { + "operator": "Default", + "resultValType": "expression", + "resultVal": "round(100*{Tab3Success}/{Tab3Total})" + } + } + ] + } + ], + "style": "pills", + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + "name": "TabInvisibleParameters" + }, + { + "type": 1, + "content": { + "json": "## App delivery" + }, + "customWidth": "50", + "name": "tab3title" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", + "size": 3, + "queryType": 8, + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 4, + "formatOptions": { + "min": 0, + "max": 100, + "palette": "redGreen" + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true + } + }, + "customWidth": "50", + "name": "TabPercentTile" + }, + { + "type": 1, + "content": { + "json": "Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." + }, + "name": "querytext0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "compliant", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "1", + "representation": "success", + "text": "Success" + }, + { + "operator": "==", + "thresholdValue": "0", + "representation": "failed", + "text": "Failed" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "Unknown" + } + ] + } + } + ] + } + }, + "name": "query0" + }, + { + "type": 1, + "content": { + "json": "Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information." + }, + "name": "querytext1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 4, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources", + "crossComponentResources": [ + "{Subscription}" + ], + "gridSettings": { + "formatters": [ + { + "columnMatch": "id", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" } } - ] - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Tab3Percent", - "type": 1, - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 }, - "criteriaData": [ - { - "criteriaContext": { - "operator": "Default", - "resultValType": "expression", - "resultVal": "round(100*{Tab3Success}/{Tab3Total})" - } + { + "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": "query1" }, { "type": 1, "content": { - "json": "## IP plan" + "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." }, - "customWidth": "50", - "name": "tab3title" + "name": "querytext2" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"Column1\\\": \\\"{Tab3Percent}\\\", \\\"Column2\\\": \\\"Percent of succesful checks\\\"}\",\"transformers\":null}", - "size": 3, - "queryType": 8, - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 4, - "formatOptions": { - "min": 0, - "max": 100, - "palette": "redGreen" + "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" + } + } }, - "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": "query2" }, { "type": 1, "content": { - "json": "Use IP addresses from the address allocation ranges for private internets (RFC 1918). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." + "json": "Deploy 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/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/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", @@ -1934,20 +2024,20 @@ ] } }, - "name": "query11" + "name": "query3" }, { "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 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/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | extend addressMask = split(addressPrefix,'/')[1] | extend compliant = addressMask > 16 | project name, id, subscriptionId, resourceGroup, addressPrefix, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/loadbalancers' | 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", @@ -1996,7 +2086,7 @@ ] } }, - "name": "query12" + "name": "query4" } ] }, @@ -2024,9 +2114,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query19Stats", + "name": "Query12Stats", "type": 1, - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type == 'microsoft.network/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}" ], @@ -2040,9 +2130,37 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query19FullyCompliant", + "name": "Query12FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query19Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query12Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 8 + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query13Stats", + "type": 1, + "query": "resources | where type == 'microsoft.network/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}" + ], + "isHiddenWhenLocked": true, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": 1, + "resourceType": "microsoft.resourcegraph/resources" + }, + { + "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", + "version": "KqlParameterItem/1.0", + "name": "Query13FullyCompliant", + "type": 1, + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2063,7 +2181,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Success}" + "resultVal": "{Query12Stats:$.Success}+{Query13Stats:$.Success}" } } ] @@ -2082,7 +2200,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query19Stats:$.Total}" + "resultVal": "{Query12Stats:$.Total}+{Query13Stats:$.Total}" } } ] @@ -2116,7 +2234,7 @@ { "type": 1, "content": { - "json": "## PaaS" + "json": "## IP plan" }, "customWidth": "50", "name": "tab4title" @@ -2138,34 +2256,96 @@ "max": 100, "palette": "redGreen" }, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + "subtitleContent": { + "columnMatch": "Column2" + }, + "showBorder": true + } + }, + "customWidth": "50", + "name": "TabPercentTile" + }, + { + "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." + }, + "name": "querytext12" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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" + } + ] } } - }, - "subtitleContent": { - "columnMatch": "Column2" - }, - "showBorder": true + ] } }, - "customWidth": "50", - "name": "TabPercentTile" + "name": "query12" }, { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "Ensure that 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": "querytext19" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -2214,7 +2394,7 @@ ] } }, - "name": "query19" + "name": "query13" } ] }, @@ -2242,7 +2422,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query24Stats", + "name": "Query25Stats", "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": [ @@ -2258,9 +2438,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query24FullyCompliant", + "name": "Query25FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query24Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query25Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2281,7 +2461,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query24Stats:$.Success}" + "resultVal": "{Query25Stats:$.Success}" } } ] @@ -2300,7 +2480,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query24Stats:$.Total}" + "resultVal": "{Query25Stats:$.Total}" } } ] @@ -2377,7 +2557,7 @@ "content": { "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext24" + "name": "querytext25" }, { "type": 3, @@ -2432,7 +2612,7 @@ ] } }, - "name": "query24" + "name": "query25" } ] }, @@ -2460,7 +2640,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4Stats", + "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": [ @@ -2476,9 +2656,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query4FullyCompliant", + "name": "Query5FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query4Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2488,7 +2668,7 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5Stats", + "name": "Query6Stats", "type": 1, "query": "resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | project id, peeringName=properties_virtualNetworkPeerings.name, compliant = (properties_virtualNetworkPeerings.properties.allowVirtualNetworkAccess == True)| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ @@ -2504,9 +2684,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query5FullyCompliant", + "name": "Query6FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query5Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query6Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2527,7 +2707,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Success}+{Query5Stats:$.Success}" + "resultVal": "{Query5Stats:$.Success}+{Query6Stats:$.Success}" } } ] @@ -2546,7 +2726,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query4Stats:$.Total}+{Query5Stats:$.Total}" + "resultVal": "{Query5Stats:$.Total}+{Query6Stats:$.Total}" } } ] @@ -2623,7 +2803,7 @@ "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." }, - "name": "querytext4" + "name": "querytext5" }, { "type": 3, @@ -2678,14 +2858,14 @@ ] } }, - "name": "query4" + "name": "query5" }, { "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": "querytext5" + "name": "querytext6" }, { "type": 3, @@ -2740,7 +2920,7 @@ ] } }, - "name": "query5" + "name": "query6" } ] }, @@ -2768,37 +2948,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query13Stats", - "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", - "crossComponentResources": [ - "{Subscription}" - ], - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources" - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query13FullyCompliant", - "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query13Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", - "isHiddenWhenLocked": true, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": 8 - }, - { - "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", - "version": "KqlParameterItem/1.0", - "name": "Query14Stats", + "name": "Query7Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -2812,9 +2964,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query14FullyCompliant", + "name": "Query7FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query14Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query7Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2824,9 +2976,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15Stats", + "name": "Query8Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -2840,9 +2992,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query15FullyCompliant", + "name": "Query8FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query15Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query8Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2852,9 +3004,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query16Stats", + "name": "Query9Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -2868,9 +3020,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query16FullyCompliant", + "name": "Query9FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query16Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query9Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2880,9 +3032,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query17Stats", + "name": "Query10Stats", "type": 1, - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -2896,9 +3048,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query17FullyCompliant", + "name": "Query10FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query17Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query10Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2908,9 +3060,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query18Stats", + "name": "Query11Stats", "type": 1, - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())", "crossComponentResources": [ "{Subscription}" ], @@ -2924,9 +3076,9 @@ { "id": "daf05c62-1d5b-4325-b241-d7ee468f23eb", "version": "KqlParameterItem/1.0", - "name": "Query18FullyCompliant", + "name": "Query11FullyCompliant", "type": 1, - "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query18Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", + "query": "{\"version\":\"1.0.0\",\"content\":\"{\\\"value\\\": \\\"{Query11Stats:$.FullyCompliant}\\\"}\",\"transformers\":null}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -2947,7 +3099,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}" + "resultVal": "{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.Success}" } } ] @@ -2966,7 +3118,7 @@ "criteriaContext": { "operator": "Default", "resultValType": "expression", - "resultVal": "{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}" + "resultVal": "{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.Total}" } } ] @@ -3000,7 +3152,7 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Hybrid" }, "customWidth": "50", "name": "tab7title" @@ -3041,77 +3193,15 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." - }, - "name": "querytext13" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", - "size": 4, - "queryType": 1, - "resourceType": "microsoft.resourcegraph/resources", - "crossComponentResources": [ - "{Subscription}" - ], - "gridSettings": { - "formatters": [ - { - "columnMatch": "id", - "formatter": 0, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "compliant", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "icons", - "thresholdsGrid": [ - { - "operator": "==", - "thresholdValue": "1", - "representation": "success", - "text": "Success" - }, - { - "operator": "==", - "thresholdValue": "0", - "representation": "failed", - "text": "Failed" - }, - { - "operator": "Default", - "thresholdValue": null, - "representation": "unknown", - "text": "Unknown" - } - ] - } - } - ] - } - }, - "name": "query13" - }, - { - "type": 1, - "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext14" + "name": "querytext7" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/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", @@ -3160,20 +3250,20 @@ ] } }, - "name": "query14" + "name": "query7" }, { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." }, - "name": "querytext15" + "name": "querytext8" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/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", @@ -3222,20 +3312,20 @@ ] } }, - "name": "query15" + "name": "query8" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." }, - "name": "querytext16" + "name": "querytext9" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/connections' | where properties.connectionType == 'ExpressRoute' | project id, gwid=tostring(properties.virtualNetworkGateway1.id), circuitid=tostring(properties.peer.id) | join (resources | where type=='microsoft.network/expressroutecircuits' | project circuitid=tostring(id), circuitsku=sku.tier) on circuitid | project id=gwid, compliant = (circuitsku == 'Local') | summarize compliant=max(compliant) by id | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -3284,20 +3374,20 @@ ] } }, - "name": "query16" + "name": "query9" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext17" + "name": "querytext10" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.intrusionDetection.mode == 'Deny') | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier contains 'AZ'| project name, id, subscriptionId, resourceGroup, Type, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -3346,20 +3436,20 @@ ] } }, - "name": "query17" + "name": "query10" }, { "type": 1, "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." }, - "name": "querytext18" + "name": "querytext11" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | extend compliant = (tolower(properties.sku.name) contains 'az') | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 4, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -3408,7 +3498,7 @@ ] } }, - "name": "query18" + "name": "query11" } ] }, diff --git a/workbooks/alz_checklist.en_network_tabcounters_template.json b/workbooks/alz_checklist.en_network_tabcounters_template.json index 23a22cafa..2a250b49a 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\": \"4f56be24-9e5b-4de8-837d-7eedbd5070c9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"81e68b16-41bc-4b82-a85e-e7c8924c2687\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab1\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"accf5249-1c25-4cb1-bbc5-96f8c9615e05\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"110d6170-cfb2-4c07-be7b-0ecff2dc9cec\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab3\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"79a832b0-b2be-4787-8067-992a9df616cd\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab4\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"cb424601-9d10-414a-8157-83fc9d17b8f7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2b0d998f-4dba-46be-b763-159034e08a2e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"feefdce7-a014-4d19-9086-f3112ae18e14\",\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\": \"Query6Stats\",\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\": \"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/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\": \"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/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\": \"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 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\": \"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/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\": \"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\": \"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\": \"{Query6Stats:$.Success}+{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.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\": \"{Query6Stats:$.Total}+{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"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 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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/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\": \"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/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\": \"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/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\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## App delivery\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"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\": \"querytext1\"\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\": \"query1\"\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\": \"querytext2\"\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\": \"query2\"\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\": \"querytext3\"\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\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query20Stats\",\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\": \"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,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\": \"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/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\": \"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,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\": \"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\": \"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\": \"{Query20Stats:$.Success}+{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"{Query20Stats:$.Total}+{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"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\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"Query11Stats\",\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\": \"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/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\": \"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\": \"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\": \"{Query11Stats:$.Success}+{Query12Stats:$.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\": \"{Query11Stats:$.Total}+{Query12Stats:$.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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"Query19Stats\",\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\": \"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\": \"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\": \"{Query19Stats:$.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\": \"{Query19Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab4title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab4Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of 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\": \"querytext19\"\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\": \"query19\"\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\": \"Query24Stats\",\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\": \"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\": \"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\": \"{Query24Stats:$.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\": \"{Query24Stats:$.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\": \"## Virtual WAN\"\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\": \"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\": \"querytext24\"\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\": \"query24\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab5\"\n },\n \"name\": \"tab5\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | 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\": \"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' | 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\": \"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\": \"Tab6Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Success}+{Query5Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab6Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query4Stats:$.Total}+{Query5Stats:$.Total}\"\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\": \"## Hub and spoke\"\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\": \"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\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"Query13Stats\",\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\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query14Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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/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\": \"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.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\": \"Query17FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query17Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query18Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,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\": \"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\": \"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\": \"{Query13Stats:$.Success}+{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.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\": \"{Query13Stats:$.Total}+{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.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/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | 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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"ba405107-7b09-4dc9-ae90-e6773d324208\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8711320c-1100-4ca2-8ce5-d7b90a03deb0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab1\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"670e23fb-092c-489b-af46-1aeaf6574f9f\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"a447f510-1c5d-4429-9d89-24f0970ee2d7\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab3\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"b91d286d-205b-454b-ae21-c59a7bfe5407\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab4\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"67ed632a-cab5-4996-b6ed-637c9d2c93d9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8cac181f-2a84-488a-a417-4c293dae16a4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"dcb189e5-2323-45af-99c8-0160f369e4a4\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab7\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 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' | 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\": \"Query14FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query14Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query15Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.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\": \"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/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\": \"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.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\": \"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.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\": \"Query18FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query18Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query19Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,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\": \"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\": \"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\": \"{Query14Stats:$.Success}+{Query15Stats:$.Success}+{Query16Stats:$.Success}+{Query17Stats:$.Success}+{Query18Stats:$.Success}+{Query19Stats:$.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\": \"{Query14Stats:$.Total}+{Query15Stats:$.Total}+{Query16Stats:$.Total}+{Query17Stats:$.Total}+{Query18Stats:$.Total}+{Query19Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab0Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab0Success}/{Tab0Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab0title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab0Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext14\"\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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"Query20Stats\",\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\": \"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\": \"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\": \"{Query20Stats:$.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\": \"{Query20Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab1Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab1Success}/{Tab1Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab1title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab1Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext20\"\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\": \"query20\"\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\": \"Query21Stats\",\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\": \"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,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\": \"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/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\": \"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,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\": \"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\": \"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\": \"{Query21Stats:$.Success}+{Query22Stats:$.Success}+{Query23Stats:$.Success}+{Query24Stats:$.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\": \"{Query21Stats:$.Total}+{Query22Stats:$.Total}+{Query23Stats:$.Total}+{Query24Stats:$.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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query0FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query0Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard')| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query1FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query1Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query2FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query2Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3Stats\",\n \"type\": 1,\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query3FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query3Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4Stats\",\n \"type\": 1,\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant| summarize Total = count(), Success = countif(compliant==1), Failed = countif(compliant==0) | extend SuccessPercent = iff(Total==0, 100, 100*toint(Success)/toint(Total)) | extend FullyCompliant = iff(SuccessPercent == 100, 'Yes', 'No') | project Query1Stats=tostring(pack_all())\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query4FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query4Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Success}+{Query1Stats:$.Success}+{Query2Stats:$.Success}+{Query3Stats:$.Success}+{Query4Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query0Stats:$.Total}+{Query1Stats:$.Total}+{Query2Stats:$.Total}+{Query3Stats:$.Total}+{Query4Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab3Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab3Success}/{Tab3Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## App delivery\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab3title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab3Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 4,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query12Stats\",\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\": \"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/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\": \"Query13FullyCompliant\",\n \"type\": 1,\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"value\\\\\\\": \\\\\\\"{Query13Stats:$.FullyCompliant}\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"queryType\": 8\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Success\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query12Stats:$.Success}+{Query13Stats:$.Success}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Total\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"{Query12Stats:$.Total}+{Query13Stats:$.Total}\"\n }\n }\n ]\n },\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Tab4Percent\",\n \"type\": 1,\n \"isHiddenWhenLocked\": true,\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"criteriaData\": [\n {\n \"criteriaContext\": {\n \"operator\": \"Default\",\n \"resultValType\": \"expression\",\n \"resultVal\": \"round(100*{Tab4Success}/{Tab4Total})\"\n }\n }\n ]\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\"\n },\n \"name\": \"TabInvisibleParameters\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## IP plan\"\n },\n \"customWidth\": \"50\",\n \"name\": \"tab4title\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"{\\\"version\\\":\\\"1.0.0\\\",\\\"content\\\":\\\"{\\\\\\\"Column1\\\\\\\": \\\\\\\"{Tab4Percent}\\\\\\\", \\\\\\\"Column2\\\\\\\": \\\\\\\"Percent of succesful checks\\\\\\\"}\\\",\\\"transformers\\\":null}\",\n \"size\": 3,\n \"queryType\": 8,\n \"visualization\": \"tiles\",\n \"tileSettings\": {\n \"titleContent\": {\n \"columnMatch\": \"Column1\",\n \"formatter\": 4,\n \"formatOptions\": {\n \"min\": 0,\n \"max\": 100,\n \"palette\": \"redGreen\"\n },\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n \"subtitleContent\": {\n \"columnMatch\": \"Column2\"\n },\n \"showBorder\": true\n }\n },\n \"customWidth\": \"50\",\n \"name\": \"TabPercentTile\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use 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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"parameters\": [\n {\n \"id\": \"daf05c62-1d5b-4325-b241-d7ee468f23eb\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Query25Stats\",\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\": \"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\": \"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\": \"{Query25Stats:$.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\": \"{Query25Stats:$.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\": \"## Virtual WAN\"\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\": \"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\": \"querytext25\"\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\": \"query25\"\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\": \"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 | 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\": \"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\": \"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\": \"{Query5Stats:$.Success}+{Query6Stats:$.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\": \"{Query5Stats:$.Total}+{Query6Stats:$.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\": \"## Hub and spoke\"\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\": \"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\": \"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\": \"querytext6\"\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\": \"query6\"\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\": \"Query7Stats\",\n \"type\": 1,\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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\": \"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/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\": \"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/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\": \"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/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\": \"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/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\": \"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\": \"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\": \"{Query7Stats:$.Success}+{Query8Stats:$.Success}+{Query9Stats:$.Success}+{Query10Stats:$.Success}+{Query11Stats:$.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\": \"{Query7Stats:$.Total}+{Query8Stats:$.Total}+{Query9Stats:$.Total}+{Query10Stats:$.Total}+{Query11Stats:$.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\": \"## Hybrid\"\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\": \"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\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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 2550526af..3c9cfdf27 100644 --- a/workbooks/alz_checklist.en_network_workbook.json +++ b/workbooks/alz_checklist.en_network_workbook.json @@ -70,34 +70,34 @@ "style": "tabs", "links": [ { - "id": "cc9f7922-f9e2-477f-9065-488cd7fba646", + "id": "2b7cd609-a137-49c7-87d4-3c4f834d79cb", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "IP plan", + "linkLabel": "Segmentation", "subTarget": "tab0", - "preText": "IP plan", + "preText": "Segmentation", "style": "primary" }, { - "id": "8b17faad-0404-45ca-8a71-631874b21e2b", + "id": "6549b183-b652-41a6-8830-f59d5eaa9b50", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hub and spoke", + "linkLabel": "Hybrid", "subTarget": "tab1", - "preText": "Hub and spoke", + "preText": "Hybrid", "style": "primary" }, { - "id": "85c2b476-271c-4f97-9cdd-86e4713a78fa", + "id": "e91fad49-bb58-4e6f-b420-0074950ef80e", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Hybrid", + "linkLabel": "Internet", "subTarget": "tab2", - "preText": "Hybrid", + "preText": "Internet", "style": "primary" }, { - "id": "e9551f2b-94df-43eb-8779-60540fc11e96", + "id": "f3ff6a57-6c88-4f8a-8dbe-137e494381ca", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "App delivery", @@ -106,39 +106,39 @@ "style": "primary" }, { - "id": "aba3e909-c09f-4740-b2a4-8128883a9f92", + "id": "e136e480-644c-46c1-9ff5-1b48ec8c4fde", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Segmentation", + "linkLabel": "Virtual WAN", "subTarget": "tab4", - "preText": "Segmentation", + "preText": "Virtual WAN", "style": "primary" }, { - "id": "2e9eb73b-cf15-4d28-bc51-535c86fd7c6d", + "id": "dadf7e49-be36-47c8-9c91-1659f7aede61", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Virtual WAN", + "linkLabel": "IP plan", "subTarget": "tab5", - "preText": "Virtual WAN", + "preText": "IP plan", "style": "primary" }, { - "id": "5c0d89df-1848-4241-91d7-5e972230a674", + "id": "77eeacc7-d104-4bc1-89fd-3dd5536fed13", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "PaaS", + "linkLabel": "Hub and spoke", "subTarget": "tab6", - "preText": "PaaS", + "preText": "Hub and spoke", "style": "primary" }, { - "id": "8b118eca-dd30-454b-902c-8f9cc897e57f", + "id": "8a6c535d-cfb3-4751-8dcb-854ba3ec49e3", "cellValue": "VisibleTab", "linkTarget": "parameter", - "linkLabel": "Internet", + "linkLabel": "PaaS", "subTarget": "tab7", - "preText": "Internet", + "preText": "PaaS", "style": "primary" } ] @@ -154,22 +154,22 @@ { "type": 1, "content": { - "json": "## IP plan" + "json": "## Segmentation" }, "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": "Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information." }, - "name": "querytext11" + "name": "querytext21" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -218,20 +218,20 @@ ] } }, - "name": "query11" + "name": "query21" }, { "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": "querytext12" + "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,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", @@ -280,42 +280,20 @@ ] } }, - "name": "query12" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab0" - }, - "name": "tab0" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Hub and spoke" - }, - "name": "tab1title" + "name": "query22" }, { "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": "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": "querytext4" + "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/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -364,20 +342,20 @@ ] } }, - "name": "query4" + "name": "query23" }, { "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": "querytext5" + "name": "querytext24" }, { "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", @@ -426,16 +404,16 @@ ] } }, - "name": "query5" + "name": "query24" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab1" + "value": "tab0" }, - "name": "tab1" + "name": "tab0" }, { "type": 12, @@ -448,14 +426,14 @@ "content": { "json": "## Hybrid" }, - "name": "tab2title" + "name": "tab1title" }, { "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": "querytext6" + "name": "querytext7" }, { "type": 3, @@ -510,14 +488,14 @@ ] } }, - "name": "query6" + "name": "query7" }, { "type": 1, "content": { "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." }, - "name": "querytext7" + "name": "querytext8" }, { "type": 3, @@ -572,14 +550,14 @@ ] } }, - "name": "query7" + "name": "query8" }, { "type": 1, "content": { "json": "Leverage the Local SKU of ExpressRoute to reduce the cost of your circuits, if your circuits' peering location supports your Azure regions for the Local SKU. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-faqs#expressroute-local) for further information." }, - "name": "querytext8" + "name": "querytext9" }, { "type": 3, @@ -634,14 +612,14 @@ ] } }, - "name": "query8" + "name": "query9" }, { "type": 1, "content": { "json": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, - "name": "querytext9" + "name": "querytext10" }, { "type": 3, @@ -696,14 +674,14 @@ ] } }, - "name": "query9" + "name": "query10" }, { "type": 1, "content": { "json": "Use VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." }, - "name": "querytext10" + "name": "querytext11" }, { "type": 3, @@ -758,16 +736,16 @@ ] } }, - "name": "query10" + "name": "query11" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab2" + "value": "tab1" }, - "name": "tab2" + "name": "tab1" }, { "type": 12, @@ -778,22 +756,22 @@ { "type": 1, "content": { - "json": "## App delivery" + "json": "## Internet" }, - "name": "tab3title" + "name": "tab2title" }, { "type": 1, "content": { - "json": "Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." }, - "name": "querytext0" + "name": "querytext14" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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", @@ -842,20 +820,20 @@ ] } }, - "name": "query0" + "name": "query14" }, { "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 FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, - "name": "querytext1" + "name": "querytext15" }, { "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.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", @@ -904,20 +882,20 @@ ] } }, - "name": "query1" + "name": "query15" }, { "type": 1, "content": { - "json": "Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information." + "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext2" + "name": "querytext16" }, { "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.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", @@ -966,20 +944,20 @@ ] } }, - "name": "query2" + "name": "query16" }, { "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": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, - "name": "querytext3" + "name": "querytext17" }, { "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/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", @@ -1028,42 +1006,20 @@ ] } }, - "name": "query3" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab3" - }, - "name": "tab3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Segmentation" - }, - "name": "tab4title" + "name": "query17" }, { "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": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." }, - "name": "querytext20" + "name": "querytext18" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureFirewallSubnet' | extend compliant = (subnetPrefixLength == 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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", @@ -1112,20 +1068,20 @@ ] } }, - "name": "query20" + "name": "query18" }, { "type": 1, "content": { - "json": "Use at least a /27 prefix for your Gateway subnets. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-howto-add-gateway-resource-manager#add-a-gateway) for further information." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, - "name": "querytext21" + "name": "querytext19" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'GatewaySubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "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", @@ -1174,20 +1130,42 @@ ] } }, - "name": "query21" + "name": "query19" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab2" + }, + "name": "tab2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## App delivery" + }, + "name": "tab3title" }, { "type": 1, "content": { - "json": "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 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/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/applicationgateways' | 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", @@ -1236,20 +1214,20 @@ ] } }, - "name": "query22" + "name": "query0" }, { "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 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": "querytext23" + "name": "querytext1" }, { "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/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", @@ -1298,42 +1276,20 @@ ] } }, - "name": "query23" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab4" - }, - "name": "tab4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "## Virtual WAN" - }, - "name": "tab5title" + "name": "query1" }, { "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": "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": "querytext24" + "name": "querytext2" }, { "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' | 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", @@ -1382,42 +1338,82 @@ ] } }, - "name": "query24" - } - ] - }, - "conditionalVisibility": { - "parameterName": "VisibleTab", - "comparison": "isEqualTo", - "value": "tab5" - }, - "name": "tab5" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ + "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." }, - "name": "tab6title" + "name": "querytext3" + }, + { + "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", + "size": 0, + "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": "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": "querytext19" + "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1466,16 +1462,16 @@ ] } }, - "name": "query19" + "name": "query4" } ] }, "conditionalVisibility": { "parameterName": "VisibleTab", "comparison": "isEqualTo", - "value": "tab6" + "value": "tab3" }, - "name": "tab6" + "name": "tab3" }, { "type": 12, @@ -1486,22 +1482,22 @@ { "type": 1, "content": { - "json": "## Internet" + "json": "## Virtual WAN" }, - "name": "tab7title" + "name": "tab4title" }, { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." }, - "name": "querytext13" + "name": "querytext25" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1550,20 +1546,42 @@ ] } }, - "name": "query13" + "name": "query25" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab4" + }, + "name": "tab4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## IP plan" + }, + "name": "tab5title" }, { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "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": "querytext14" + "name": "querytext12" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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", @@ -1612,20 +1630,20 @@ ] } }, - "name": "query14" + "name": "query12" }, { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Ensure that IP address space isn't wasted, don't create unnecessarily large virtual networks (for example /16). Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/plan-for-ip-addressing) for further information.. [This training](https://learn.microsoft.com/learn/paths/architect-network-infrastructure/) can help to educate yourself on this." }, - "name": "querytext15" + "name": "querytext13" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.sku.tier == 'Premium') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -1674,20 +1692,42 @@ ] } }, - "name": "query15" + "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": "## Hub and spoke" + }, + "name": "tab6title" }, { "type": 1, "content": { - "json": "Configure Azure Firewall Threat Intelligence mode to Alert and Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "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": "querytext16" + "name": "querytext5" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.threatIntelMode == 'Deny') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -1736,20 +1776,20 @@ ] } }, - "name": "query16" + "name": "query5" }, { "type": 1, "content": { - "json": "Configure Azure Firewall IDPS mode to Deny for additional protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features#idps) for further information." + "json": "Use 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": "querytext17" + "name": "querytext6" }, { "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' | 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", @@ -1798,20 +1838,42 @@ ] } }, - "name": "query17" + "name": "query6" + } + ] + }, + "conditionalVisibility": { + "parameterName": "VisibleTab", + "comparison": "isEqualTo", + "value": "tab6" + }, + "name": "tab6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## PaaS" + }, + "name": "tab7title" }, { "type": 1, "content": { - "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." + "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." }, - "name": "querytext18" + "name": "querytext20" }, { "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1860,7 +1922,7 @@ ] } }, - "name": "query18" + "name": "query20" } ] }, diff --git a/workbooks/alz_checklist.en_network_workbook_template.json b/workbooks/alz_checklist.en_network_workbook_template.json index b5f46beea..e92552ae7 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\": \"cc9f7922-f9e2-477f-9065-488cd7fba646\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab0\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8b17faad-0404-45ca-8a71-631874b21e2b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"85c2b476-271c-4f97-9cdd-86e4713a78fa\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e9551f2b-94df-43eb-8779-60540fc11e96\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab3\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"aba3e909-c09f-4740-b2a4-8128883a9f92\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"2e9eb73b-cf15-4d28-bc51-535c86fd7c6d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab5\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"5c0d89df-1848-4241-91d7-5e972230a674\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab6\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8b118eca-dd30-454b-902c-8f9cc897e57f\",\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hub and spoke\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"## Hybrid\"\n },\n \"name\": \"tab2title\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"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 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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## App delivery\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"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\": \"querytext1\"\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\": \"query1\"\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\": \"querytext2\"\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\": \"query2\"\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\": \"querytext3\"\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\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## 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\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab4\"\n },\n \"name\": \"tab4\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab5title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext24\"\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\": \"query24\"\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\": \"querytext19\"\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\": \"query19\"\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/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext13\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | 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\": \"query13\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"2b7cd609-a137-49c7-87d4-3c4f834d79cb\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Segmentation\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Segmentation\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"6549b183-b652-41a6-8830-f59d5eaa9b50\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hybrid\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Hybrid\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e91fad49-bb58-4e6f-b420-0074950ef80e\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Internet\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Internet\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"f3ff6a57-6c88-4f8a-8dbe-137e494381ca\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"App delivery\",\n \"subTarget\": \"tab3\",\n \"preText\": \"App delivery\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"e136e480-644c-46c1-9ff5-1b48ec8c4fde\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Virtual WAN\",\n \"subTarget\": \"tab4\",\n \"preText\": \"Virtual WAN\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"dadf7e49-be36-47c8-9c91-1659f7aede61\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"IP plan\",\n \"subTarget\": \"tab5\",\n \"preText\": \"IP plan\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"77eeacc7-d104-4bc1-89fd-3dd5536fed13\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Hub and spoke\",\n \"subTarget\": \"tab6\",\n \"preText\": \"Hub and spoke\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"8a6c535d-cfb3-4751-8dcb-854ba3ec49e3\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"PaaS\",\n \"subTarget\": \"tab7\",\n \"preText\": \"PaaS\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Segmentation\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use a /26 prefix for your Azure Firewall subnets. Check [this link](https://learn.microsoft.com/azure/firewall/firewall-faq#why-does-azure-firewall-need-a--26-subnet-size) for further information.\"\n },\n \"name\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Hybrid\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext7\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab1\"\n },\n \"name\": \"tab1\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Internet\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext14\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | 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\": \"query14\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\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\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## App delivery\"\n },\n \"name\": \"tab3title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/applicationgateways' | project id, compliant = properties.sku.name in ('Standard_v2', 'WAF_v2') | project id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using the Standard SKU for your Azure Load Balancers. Check [this link](https://learn.microsoft.com/azure/load-balancer/load-balancer-overview) for further information.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/loadbalancers' | project id, compliant=(tolower(sku.name) == 'standard') | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Deploy your WAF profiles for Front Door in 'Prevention' mode. Check [this link](https://learn.microsoft.com/azure/web-application-firewall/afds/waf-front-door-policy-settings) for further information.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type == 'microsoft.network/frontdoorwebapplicationfirewallpolicies' | project policyName=name, policyId=id,policySku=sku.name, links=properties.securityPolicyLinks, enabledState=properties.policySettings.enabledState, mode=properties.policySettings.mode | mvexpand links | extend securityPolicy=links.id | extend securityPolicyParts=split(securityPolicy, '/') | extend profileId=strcat_array(array_slice(securityPolicyParts, 0, -3), '/') | project id=profileId, compliant=((enabledState=='Enabled') and (mode=='Prevention')), enabledState, mode | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure NAT Gateway instead of Load Balancer outbound rules for better SNAT scalability. Check [this link](https://learn.microsoft.com/azure/nat-gateway/nat-overview#outbound-connectivity) for further information.\"\n },\n \"name\": \"querytext4\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/loadbalancers' | extend countOutRules=array_length(properties.outboundRules) | extend compliant = (countOutRules == 0) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query4\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab3\"\n },\n \"name\": \"tab3\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Virtual WAN\"\n },\n \"name\": \"tab4title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext25\"\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\": \"query25\"\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\": \"## IP plan\"\n },\n \"name\": \"tab5title\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"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\": \"## Hub and spoke\"\n },\n \"name\": \"tab6title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information.\"\n },\n \"name\": \"querytext5\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'RouteServerSubnet' | extend compliant = (subnetPrefixLength <= 27) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query5\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"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\": \"querytext6\"\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\": \"query6\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab6\"\n },\n \"name\": \"tab6\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## PaaS\"\n },\n \"name\": \"tab7title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this.\"\n },\n \"name\": \"querytext20\"\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\": \"query20\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab7\"\n },\n \"name\": \"tab7\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]" diff --git a/workbooks/alz_checklist.en_workbook.json b/workbooks/alz_checklist.en_workbook.json index af10d10c0..8477ac8d7 100644 --- a/workbooks/alz_checklist.en_workbook.json +++ b/workbooks/alz_checklist.en_workbook.json @@ -70,7 +70,7 @@ "style": "tabs", "links": [ { - "id": "968aee27-f898-485e-b70e-bd40df80b40b", + "id": "c51b5de3-1d0c-484a-9d0d-109bb2b11dd9", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Network Topology and Connectivity", @@ -79,7 +79,7 @@ "style": "primary" }, { - "id": "475bedbd-7926-4945-a59a-63ee8d555273", + "id": "3fe00c15-2ec7-49bf-8e70-124533c3082d", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Security, Governance and Compliance", @@ -88,7 +88,7 @@ "style": "primary" }, { - "id": "17993c70-14d1-4653-807b-5163bc01f0b0", + "id": "67572308-8651-4bd2-a4b1-cc036c8387f0", "cellValue": "VisibleTab", "linkTarget": "parameter", "linkLabel": "Management Group and Subscriptions", @@ -178,7 +178,7 @@ { "type": 1, "content": { - "json": "Your application gateways should be deployed in subnets with IP prefixes equal or larger than /26. Check [this link](https://learn.microsoft.com/azure/application-gateway/configuration-infrastructure#size-of-the-subnet) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this." + "json": "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": "querytext5" }, @@ -186,7 +186,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/applicationgateways' | extend subnetId = tostring(properties.gatewayIPConfigurations[0].properties.subnet.id) | project id, subnetId | join (resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetId = tostring(subnets.id), subnetPrefixLength = split(subnets.properties.addressPrefix, '/')[1]) on subnetId | extend compliant = (subnetPrefixLength <= 26) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/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", @@ -240,7 +240,7 @@ { "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": "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": "querytext6" }, @@ -248,7 +248,7 @@ "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/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", @@ -302,7 +302,7 @@ { "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": "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": "querytext7" }, @@ -310,7 +310,7 @@ "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/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", @@ -364,7 +364,7 @@ { "type": 1, "content": { - "json": "If using Route Server, use a /27 prefix for the Route Server subnet. Check [this link](https://learn.microsoft.com/azure/route-server/quickstart-configure-route-server-portal#create-a-route-server-1) for further information." + "json": "Use Azure 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": "querytext8" }, @@ -372,7 +372,7 @@ "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/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", @@ -426,7 +426,7 @@ { "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": "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": "querytext9" }, @@ -434,7 +434,7 @@ "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,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", @@ -488,7 +488,7 @@ { "type": 1, "content": { - "json": "Ensure that you're using the right SKU for the ExpressRoute/VPN gateways based on bandwidth and performance requirements. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-routing) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." + "json": "Use 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": "querytext10" }, @@ -496,7 +496,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !in ('Basic', 'Standard')| project name, id, subscriptionId, resourceGroup, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | 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", @@ -550,7 +550,7 @@ { "type": 1, "content": { - "json": "Ensure that you're using unlimited-data ExpressRoute circuits only if you reach the bandwidth that justifies their cost. Check [this link](https://learn.microsoft.com/azure/expressroute/plan-manage-cost) for further information." + "json": "Ensure that 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": "querytext11" }, @@ -558,7 +558,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/expressroutecircuits' | extend compliant = (tolower(sku.family) == 'metereddata' or tolower(sku.tier) == 'local') | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources| where type == 'microsoft.network/virtualnetworkgateways'| where properties.gatewayType =~ 'vpn' or properties.gatewayType == 'ExpressRoute'| extend SKUName = properties.sku.name, SKUTier = properties.sku.tier, Type = properties.gatewayType| extend compliant = SKUTier !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", @@ -612,7 +612,7 @@ { "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": "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": "querytext12" }, @@ -620,7 +620,7 @@ "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/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", @@ -674,7 +674,7 @@ { "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": "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": "querytext13" }, @@ -682,7 +682,7 @@ "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/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", @@ -736,7 +736,7 @@ { "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": "Deploy a zone-redundant ExpressRoute gateway in the supported Azure regions. Check [this link](https://learn.microsoft.com/azure/expressroute/expressroute-about-virtual-network-gateways) for further information.. [This training](https://learn.microsoft.com/learn/modules/design-implement-azure-expressroute/) can help to educate yourself on this." }, "name": "querytext14" }, @@ -744,7 +744,7 @@ "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/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", @@ -798,7 +798,7 @@ { "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 VPN gateways to connect branches or remote locations to Azure. For higher resilience, deploy zone-redundant gateways (where available). Check [this link](https://learn.microsoft.com/azure/vpn-gateway/create-zone-redundant-vnet-gateway) for further information.. [This training](https://learn.microsoft.com/training/modules/intro-to-azure-vpn-gateway/) can help to educate yourself on this." }, "name": "querytext15" }, @@ -806,7 +806,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | project name, id, location, resourceGroup, subscriptionId, cidr = addressPrefix | extend compliant = (cidr matches regex @'^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\\.168\\.)') | project id, compliant, cidr | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworkgateways' | where properties.gatewayType == 'Vpn' | 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", @@ -860,7 +860,7 @@ { "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 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": "querytext16" }, @@ -868,7 +868,7 @@ "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' | 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", @@ -922,7 +922,7 @@ { "type": 1, "content": { - "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." + "json": "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": "querytext17" }, @@ -930,7 +930,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == 'AzureBastionSubnet' | extend compliant = (subnetPrefixLength <= 26) | distinct id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type == 'microsoft.network/virtualnetworks' | extend addressSpace = todynamic(properties.addressSpace) | extend addressPrefix = todynamic(properties.addressSpace.addressPrefixes) | mvexpand addressSpace | mvexpand addressPrefix | 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", @@ -984,7 +984,7 @@ { "type": 1, "content": { - "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." + "json": "Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information." }, "name": "querytext18" }, @@ -992,7 +992,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/firewallpolicies' | extend compliant = (properties.dnsSettings.enableProxy == true) | distinct id,compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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", @@ -1046,7 +1046,7 @@ { "type": 1, "content": { - "json": "Use Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." + "json": "Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information." }, "name": "querytext19" }, @@ -1054,7 +1054,7 @@ "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/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", @@ -1108,7 +1108,7 @@ { "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 Azure Firewall Premium for additional security and protection. Check [this link](https://learn.microsoft.com/azure/firewall/premium-features) for further information." }, "name": "querytext20" }, @@ -1116,7 +1116,7 @@ "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/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", @@ -1170,7 +1170,7 @@ { "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": "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": "querytext21" }, @@ -1178,7 +1178,7 @@ "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/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", @@ -1232,7 +1232,7 @@ { "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": "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": "querytext22" }, @@ -1240,7 +1240,7 @@ "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/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", @@ -1294,7 +1294,7 @@ { "type": 1, "content": { - "json": "Don't enable virtual network service endpoints by default on all subnets. Check [this link](https://learn.microsoft.com/azure/app-service/networking-features) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-network-security/?source=learn) can help to educate yourself on this." + "json": "For subnets in VNets not connected to Virtual WAN, attach a route table so that Internet traffic is redirected to Azure Firewall or a Network Virtual Appliance. Check [this link](https://learn.microsoft.com/azure/virtual-network/virtual-networks-udr-overview) for further information." }, "name": "querytext23" }, @@ -1302,7 +1302,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type =~ 'microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets = properties.subnets | mv-expand subnets | project id = subnets.id, resourceGroup, VNet = name, serviceEndpoints = subnets.properties.serviceEndpoints, compliant = (isnull(subnets.properties.serviceEndpoints) or array_length(subnets.properties.serviceEndpoints) == 0) | order by compliant asc | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,resourceGroup,name,subnets=properties.subnets | mv-expand subnets | project id,name,subnetId=tostring(subnets.id), subnetName=tostring(subnets.name),subnetRT=subnets.properties.routeTable.id | where not (subnetName in ('GatewaySubnet', 'AzureFirewallSubnet', 'RouteServerSubnet', 'AzureBastionSubnet')) | extend hasRT = isnotnull(subnetRT) | distinct id, hasRT, subnetId | join kind=fullouter (resources | where type == 'microsoft.network/virtualnetworks' | mvexpand properties.virtualNetworkPeerings | extend isVWAN=(tolower(split(properties_virtualNetworkPeerings.name, '_')[0]) == 'remotevnettohubpeering') | mv-expand properties.subnets | project id, isVWAN, name, subnetId=tostring(properties_subnets.id), subnetName=tostring(properties_subnets.name) | summarize PeeredToVWAN=max(isVWAN) by id, subnetId | project id, subnetId, isVWANpeer = (PeeredToVWAN == true)) on subnetId | project id=iff(isnotempty(id), id, id1), subnetId=iff(isnotempty(subnetId), subnetId, subnetId1), hasRT, isVWANpeer | extend compliant = (hasRT==true or isVWANpeer==true) | distinct id, subnetId, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", "size": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1356,7 +1356,7 @@ { "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": "querytext24" }, @@ -1364,7 +1364,7 @@ "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": 0, "queryType": 1, "resourceType": "microsoft.resourcegraph/resources", @@ -1418,7 +1418,7 @@ { "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 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": "querytext25" }, @@ -1426,7 +1426,7 @@ "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' | 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", @@ -1480,7 +1480,7 @@ { "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 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": "querytext26" }, @@ -1488,7 +1488,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/networksecuritygroups' | mvexpand properties.securityRules | project id,name,ruleAction=properties_securityRules.properties.access,rulePriority=properties_securityRules.properties.priority,ruleDst=properties_securityRules.properties.destinationAddressPrefix,ruleSrc=properties_securityRules.properties.sourceAddressPrefix,ruleProt=properties_securityRules.properties.protocol,ruleDirection=properties_securityRules.properties.direction,rulePort=properties_securityRules.properties.destinationPortRange | summarize StarDenies=countif(ruleAction=='Deny' and ruleDst=='*' and ruleSrc=='*' and ruleProt=='*' and rulePort=='*') by id,tostring(ruleDirection) | where ruleDirection == 'Inbound' | project id,compliant=(StarDenies>0) | union (resources | where type=='microsoft.network/networksecuritygroups' | where array_length(properties.securityRules)==0 | extend compliant=false | project id,compliant) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -1542,7 +1542,7 @@ { "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": "Don't rely on the NSG inbound default rules using the VirtualNetwork service tag to limit connectivity. Check [this link](https://learn.microsoft.com/azure/virtual-network/service-tags-overview#available-service-tags) for further information." }, "name": "querytext27" }, @@ -1550,7 +1550,7 @@ "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/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", @@ -1604,7 +1604,7 @@ { "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": "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": "querytext28" }, @@ -1612,7 +1612,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "query": "Resources | where type=='microsoft.network/virtualnetworks' | project id,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", @@ -1662,6 +1662,68 @@ } }, "name": "query28" + }, + { + "type": 1, + "content": { + "json": "For outbound Internet traffic protection and filtering, deploy Azure Firewall in secured hubs. Check [this link](https://learn.microsoft.com/azure/virtual-wan/virtual-wan-about) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-networking-infrastructure/) can help to educate yourself on this." + }, + "name": "querytext29" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "resources | where type=='microsoft.network/virtualhubs' | extend compliant = isnotnull(properties.azureFirewall.id) | project id, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed", + "size": 0, + "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": "query29" } ] }, @@ -1690,7 +1752,7 @@ "content": { "json": "Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information." }, - "name": "querytext29" + "name": "querytext30" }, { "type": 3, @@ -1745,7 +1807,7 @@ ] } }, - "name": "query29" + "name": "query30" } ] }, diff --git a/workbooks/alz_checklist.en_workbook_template.json b/workbooks/alz_checklist.en_workbook_template.json index aebe421fc..e7b314150 100644 --- a/workbooks/alz_checklist.en_workbook_template.json +++ b/workbooks/alz_checklist.en_workbook_template.json @@ -41,7 +41,7 @@ "dependsOn": [], "properties": { "displayName": "[parameters('workbookDisplayName')]", - "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"968aee27-f898-485e-b70e-bd40df80b40b\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"475bedbd-7926-4945-a59a-63ee8d555273\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security, Governance and Compliance\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security, Governance and Compliance\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"17993c70-14d1-4653-807b-5163bc01f0b0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Management Group and Subscriptions\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Management Group and Subscriptions\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"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' 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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"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 | 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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext17\"\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\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext18\"\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\": \"query18\"\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\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"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,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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"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 == '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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"querytext27\"\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\": \"query27\"\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\": \"querytext28\"\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\": \"query28\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Security, Governance and Compliance\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext29\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query29\"\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\": \"## Management Group and Subscriptions\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than three to four levels, ideally. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", + "serializedData": "{\n \"version\": \"Notebook/1.0\",\n \"items\": [\n {\n \"type\": 9,\n \"content\": {\n \"version\": \"KqlParameterItem/1.0\",\n \"parameters\": [\n {\n \"id\": \"497a107e-dde8-433e-b263-35ac8e8f7834\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"Subscription\",\n \"type\": 6,\n \"multiSelect\": true,\n \"quote\": \"'\",\n \"delimiter\": \",\",\n \"typeSettings\": {\n \"additionalResourceOptions\": [\n \"value::all\"\n ],\n \"includeAll\": true,\n \"showDefault\": false\n },\n \"timeContext\": {\n \"durationMs\": 86400000\n },\n \"value\": [\n \"value::all\"\n ]\n },\n {\n \"id\": \"844e4f4e-df51-4e3c-8eaf-0dc78b92c721\",\n \"version\": \"KqlParameterItem/1.0\",\n \"name\": \"OnlyFailed\",\n \"label\": \"Only show failed\",\n \"type\": 2,\n \"typeSettings\": {\n \"additionalResourceOptions\": [],\n \"showDefault\": false\n },\n \"jsonData\": \"[\\r\\n { \\\"value\\\":true, \\\"label\\\":\\\"True\\\" },\\r\\n { \\\"value\\\":false, \\\"label\\\":\\\"False\\\", \\\"selected\\\":true }\\r\\n]\"\n }\n ],\n \"style\": \"pills\",\n \"queryType\": 0,\n \"resourceType\": \"microsoft.operationalinsights/workspaces\"\n },\n \"name\": \"WorkbookSelectors\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"If you set \\\"Only show failed\\\" to \\\"Yes\\\", the different queries will only show items that have failed their compliance checks.\",\n \"style\": \"info\"\n },\n \"name\": \"InfoBox\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Azure Landing Zone Review\\n\\n---\\n\\nThis workbook has been automatically generated out of the checklists in the [Azure Review Checklists repo](https://github.com/Azure/review-checklists). This repo contains best practices and recommendations around generic Landing Zones as well as specific services such as Azure Virtual Desktop, Azure Kubernetes Service or Azure VMware Solution, to name a few. This repository of best practices is curated by Azure engineers, but open to anybody to contribute.\\n\\nIf you see a problem in the queries that are part of this workbook, please open a Github issue [here](https://github.com/Azure/review-checklists/issues/new).\"\n },\n \"customWidth\": \"100\",\n \"name\": \"MarkdownHeader\"\n },\n {\n \"type\": 11,\n \"content\": {\n \"version\": \"LinkItem/1.0\",\n \"style\": \"tabs\",\n \"links\": [\n {\n \"id\": \"c51b5de3-1d0c-484a-9d0d-109bb2b11dd9\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Network Topology and Connectivity\",\n \"subTarget\": \"tab0\",\n \"preText\": \"Network Topology and Connectivity\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"3fe00c15-2ec7-49bf-8e70-124533c3082d\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Security, Governance and Compliance\",\n \"subTarget\": \"tab1\",\n \"preText\": \"Security, Governance and Compliance\",\n \"style\": \"primary\"\n },\n {\n \"id\": \"67572308-8651-4bd2-a4b1-cc036c8387f0\",\n \"cellValue\": \"VisibleTab\",\n \"linkTarget\": \"parameter\",\n \"linkLabel\": \"Management Group and Subscriptions\",\n \"subTarget\": \"tab2\",\n \"preText\": \"Management Group and Subscriptions\",\n \"style\": \"primary\"\n }\n ]\n },\n \"name\": \"Tabs\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Network Topology and Connectivity\"\n },\n \"name\": \"tab0title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure you are using Application Gateway v2 SKU. Check [this link](https://learn.microsoft.com/azure/application-gateway/overview-v2) for further information.. [This training](https://learn.microsoft.com/learn/paths/secure-application-delivery/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext4\"\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\": \"query4\"\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\": \"querytext5\"\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\": \"query5\"\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\": \"querytext6\"\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\": \"query6\"\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\": \"querytext7\"\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\": \"query7\"\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\": \"querytext8\"\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\": \"query8\"\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\": \"querytext9\"\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\": \"query9\"\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\": \"querytext10\"\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\": \"query10\"\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\": \"querytext11\"\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\": \"query11\"\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\": \"querytext12\"\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\": \"query12\"\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\": \"querytext13\"\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\": \"query13\"\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\": \"querytext14\"\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\": \"query14\"\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\": \"querytext15\"\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\": \"query15\"\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\": \"querytext16\"\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\": \"query16\"\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\": \"querytext17\"\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\": \"query17\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use Azure Bastion in a subnet /26 or larger. Check [this link](https://learn.microsoft.com/en-us/azure/bastion/bastion-faq#subnet) for further information.\"\n },\n \"name\": \"querytext18\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | where type=='microsoft.network/virtualnetworks' | project id,subnets=properties.subnets | mv-expand subnets | project id, subnetName = subnets.name, subnetPrefix = subnets.properties.addressPrefix | extend subnetPrefixLength = split(subnetPrefix, '/')[1] | where subnetName == '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\": \"query18\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use FQDN-based network rules and Azure Firewall with DNS proxy to filter egress traffic to the Internet not supported by application rules. Check [this link](https://learn.microsoft.com/azure/firewall/fqdn-filtering-network-rules) for further information.\"\n },\n \"name\": \"querytext19\"\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\": \"query19\"\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\": \"querytext20\"\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\": \"query20\"\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\": \"querytext21\"\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\": \"query21\"\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\": \"querytext22\"\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\": \"query22\"\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\": \"querytext23\"\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\": \"query23\"\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\": \"querytext24\"\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\": \"query24\"\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\": \"querytext25\"\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\": \"query25\"\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\": \"querytext26\"\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\": \"query26\"\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\": \"querytext27\"\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\": \"query27\"\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\": \"querytext28\"\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\": \"query28\"\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\": \"querytext29\"\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\": \"query29\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab0\"\n },\n \"name\": \"tab0\"\n },\n {\n \"type\": 12,\n \"content\": {\n \"version\": \"NotebookGroup/1.0\",\n \"groupType\": \"editable\",\n \"items\": [\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"## Security, Governance and Compliance\"\n },\n \"name\": \"tab1title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Use different Azure Key Vaults for different applications and regions to avoid transaction scale limits and restrict access to secrets. Check [this link](https://learn.microsoft.com/azure/key-vault/general/overview-throttling) for further information.\"\n },\n \"name\": \"querytext30\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"ResourceContainers | where type=='microsoft.resources/subscriptions'| parse id with '/subscriptions/' SubscriptionID| project subscriptionId, SubscriptionName = name| join kind=leftouter (Resources| where type == 'microsoft.keyvault/vaults'| project id, name, subscriptionId) on subscriptionId| join kind= leftouter (Resources| where type == 'microsoft.keyvault/vaults'| summarize ResourceCount = count() by subscriptionId) on subscriptionId| extend RCount = iff(isnull(ResourceCount), 0, ResourceCount)| project-away ResourceCount| extend compliant = (RCount <> 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query30\"\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\": \"## Management Group and Subscriptions\"\n },\n \"name\": \"tab2title\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce reasonably flat management group hierarchy with no more than three to four levels, ideally. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/resource-org-management-groups) for further information.. [This training](https://learn.microsoft.com/learn/modules/azure-architecture-fundamentals/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext0\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant =( array_length(mgmtChain) <= 4 and array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query0\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce or appended resource tags through Azure Policy. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/resource-tagging/?toc=/azure/azure-resource-manager/management/toc.json) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext1\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query1\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Enforce no subscriptions are placed under the root management group. Check [this link](https://learn.microsoft.com/azure/governance/management-groups/how-to/protect-resource-hierarchy#setting---default-management-group) for further information.\"\n },\n \"name\": \"querytext2\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resourcecontainers| where type == 'microsoft.resources/subscriptions'| extend ManagementGroup = tostring(tags),mgmtChain = properties.managementGroupAncestorsChain| extend compliant = (array_length(mgmtChain) > 1) | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query2\"\n },\n {\n \"type\": 1,\n \"content\": {\n \"json\": \"Ensure tags are used for billing and cost management. Check [this link](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/track-costs) for further information.. [This training](https://learn.microsoft.com/learn/paths/implement-resource-mgmt-security/) can help to educate yourself on this.\"\n },\n \"name\": \"querytext3\"\n },\n {\n \"type\": 3,\n \"content\": {\n \"version\": \"KqlItem/1.0\",\n \"query\": \"resources | extend compliant = isnotnull(['tags']) | project name, id, subscriptionId, resourceGroup, tags, compliant | extend onlyFailed = {OnlyFailed:label} | where compliant == 0 or not (onlyFailed == 1) | project-away onlyFailed\",\n \"size\": 0,\n \"queryType\": 1,\n \"resourceType\": \"microsoft.resourcegraph/resources\",\n \"crossComponentResources\": [\n \"{Subscription}\"\n ],\n \"gridSettings\": {\n \"formatters\": [\n {\n \"columnMatch\": \"id\",\n \"formatter\": 0,\n \"numberFormat\": {\n \"unit\": 0,\n \"options\": {\n \"style\": \"decimal\"\n }\n }\n },\n {\n \"columnMatch\": \"compliant\",\n \"formatter\": 18,\n \"formatOptions\": {\n \"thresholdsOptions\": \"icons\",\n \"thresholdsGrid\": [\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"1\",\n \"representation\": \"success\",\n \"text\": \"Success\"\n },\n {\n \"operator\": \"==\",\n \"thresholdValue\": \"0\",\n \"representation\": \"failed\",\n \"text\": \"Failed\"\n },\n {\n \"operator\": \"Default\",\n \"thresholdValue\": null,\n \"representation\": \"unknown\",\n \"text\": \"Unknown\"\n }\n ]\n }\n }\n ]\n }\n },\n \"name\": \"query3\"\n }\n ]\n },\n \"conditionalVisibility\": {\n \"parameterName\": \"VisibleTab\",\n \"comparison\": \"isEqualTo\",\n \"value\": \"tab2\"\n },\n \"name\": \"tab2\"\n }\n ],\n \"$schema\": \"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"\n}", "version": "1.0", "sourceId": "[parameters('workbookSourceId')]", "category": "[parameters('workbookType')]"